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 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 e0f4c73aedf5ae47e9d935477ac6eaacbdd5f22b Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 21 Jun 2021 10:44:32 +0200 Subject: [PATCH 097/196] Move from experimental --- .../{experimental => }/Security/CWE/CWE-273/UnsafeCertTrust.java | 0 .../Security/CWE/CWE-273/UnsafeCertTrust.qhelp | 0 .../{experimental => }/Security/CWE/CWE-273/UnsafeCertTrust.ql | 0 .../query-tests/security/CWE-273/UnsafeCertTrust.qlref | 1 - .../query-tests/security/CWE-273/UnsafeCertTrust.expected | 0 java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref | 1 + .../query-tests/security/CWE-273/UnsafeCertTrustTest.java | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename java/ql/src/{experimental => }/Security/CWE/CWE-273/UnsafeCertTrust.java (100%) rename java/ql/src/{experimental => }/Security/CWE/CWE-273/UnsafeCertTrust.qhelp (100%) rename java/ql/src/{experimental => }/Security/CWE/CWE-273/UnsafeCertTrust.ql (100%) delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.qlref rename java/ql/test/{experimental => }/query-tests/security/CWE-273/UnsafeCertTrust.expected (100%) create mode 100644 java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref rename java/ql/test/{experimental => }/query-tests/security/CWE-273/UnsafeCertTrustTest.java (100%) diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.java b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.java rename to java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp rename to java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql rename to java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.qlref b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.qlref deleted file mode 100644 index f054d603787..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.expected similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected rename to java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.expected diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref new file mode 100644 index 00000000000..e63adf79e5e --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-273/UnsafeCertTrust.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java rename to java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java From 4313baf6228885378fa85612ebd61a8581e97a19 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 21 Jun 2021 17:36:50 +0200 Subject: [PATCH 098/196] Big refactor: - Move classes and predicates to appropriate libraries - Overhaul the endpoint identification algorithm logic to use taint tracking - Adapt tests --- .../code/java/frameworks/Networking.qll | 20 ++ .../semmle/code/java/security/Encryption.qll | 31 ++- .../code/java/security/UnsafeCertTrust.qll | 103 ++++++++ .../Security/CWE/CWE-273/UnsafeCertTrust.ql | 161 ++----------- .../security/CWE-273/UnsafeCertTrustTest.java | 124 ++++++++-- .../test/query-tests/security/CWE-273/options | 1 + .../rabbitmq/client/ConnectionFactory.java | 223 ++++++++++++++++++ 7 files changed, 494 insertions(+), 169 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll create mode 100644 java/ql/test/query-tests/security/CWE-273/options create mode 100644 java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java diff --git a/java/ql/lib/semmle/code/java/frameworks/Networking.qll b/java/ql/lib/semmle/code/java/frameworks/Networking.qll index 6e5ad743d44..7be77e26d64 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Networking.qll @@ -14,6 +14,11 @@ class TypeSocket extends RefType { TypeSocket() { this.hasQualifiedName("java.net", "Socket") } } +/** The type `javax.net.SocketFactory` */ +class TypeSocketFactory extends RefType { + TypeSocketFactory() { this.hasQualifiedName("javax.net", "SocketFactory") } +} + /** The type `java.net.URL`. */ class TypeUrl extends RefType { TypeUrl() { this.hasQualifiedName("java.net", "URL") } @@ -143,6 +148,21 @@ class UrlOpenConnectionMethod extends Method { } } +/** The method `javax.net.SocketFactory::createSocket`. */ +class CreateSocketMethod extends Method { + CreateSocketMethod() { + this.hasName("createSocket") and + this.getDeclaringType() instanceof TypeSocketFactory + } +} + +class SocketConnectMethod extends Method { + SocketConnectMethod() { + this.hasName("connect") and + this.getDeclaringType() instanceof TypeSocket + } +} + /** * A string matching private host names of IPv4 and IPv6, which only matches the host portion therefore checking for port is not necessary. * Several examples are localhost, reserved IPv4 IP addresses including 127.0.0.1, 10.x.x.x, 172.16.x,x, 192.168.x,x, and reserved IPv6 addresses including [0:0:0:0:0:0:0:1] and [::1] diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index 8f4cef23ee6..3ae5fdf3d9d 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -34,6 +34,19 @@ class SSLSession extends RefType { SSLSession() { this.hasQualifiedName("javax.net.ssl", "SSLSession") } } +class SSLEngine extends RefType { + SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } +} + +class SSLSocket extends RefType { + SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } +} + +/** The `javax.net.ssl.SSLParameters` class. */ +class SSLParameters extends RefType { + SSLParameters() { this.hasQualifiedName("javax.net.ssl", "SSLParameters") } +} + class HostnameVerifier extends RefType { HostnameVerifier() { this.hasQualifiedName("javax.net.ssl", "HostnameVerifier") } } @@ -79,6 +92,14 @@ class GetSocketFactory extends Method { } } +/** The `createSSLEngine` method of the class `javax.net.ssl.SSLContext` */ +class CreateSslEngineMethod extends Method { + CreateSslEngineMethod() { + this.hasName("createSSLEngine") and + this.getDeclaringType() instanceof SSLContext + } +} + class SetConnectionFactoryMethod extends Method { SetConnectionFactoryMethod() { this.hasName("setSSLSocketFactory") and @@ -101,6 +122,14 @@ class SetDefaultHostnameVerifierMethod extends Method { } } +/** The `getSession` method of the class `javax.net.ssl.SSLSession`.select */ +class GetSslSessionMethod extends Method { + GetSslSessionMethod() { + hasName("getSession") and + getDeclaringType().getASupertype*() instanceof SSLSession + } +} + bindingset[algorithmString] private string algorithmRegex(string algorithmString) { // Algorithms usually appear in names surrounded by characters that are not @@ -168,7 +197,7 @@ string getInsecureAlgorithmRegex() { string getASecureAlgorithmName() { result = [ - "RSA", "SHA256", "SHA512", "CCM", "GCM", "AES(?![^a-zA-Z](ECB|CBC/PKCS[57]Padding))", + "RSA", "SHA256", "SHA512", "CCM", "GCM", "AES([^a-zA-Z](?!ECB|CBC/PKCS[57]Padding)).*", "Blowfish", "ECIES" ] } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll new file mode 100644 index 00000000000..4dfa16e2078 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -0,0 +1,103 @@ +/** Provides classes and predicates to reason about unsafe certificate trust vulnerablities. */ + +import java +private import semmle.code.java.frameworks.Networking +private import semmle.code.java.security.Encryption +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.DataFlow2 + +/** + * The creation of an object that prepares an SSL connection. + */ +class SslConnectionInit extends DataFlow::Node { + SslConnectionInit() { + this.asExpr().(MethodAccess).getMethod() instanceof CreateSslEngineMethod or + this.asExpr().(MethodAccess).getMethod() instanceof CreateSocketMethod + } +} + +/** + * A call to a method that establishes an SSL connection. + */ +class SslConnectionCreation extends DataFlow::Node { + SslConnectionCreation() { + exists(MethodAccess ma, Method m | + m instanceof GetSslSessionMethod or + m instanceof SocketConnectMethod + | + ma.getMethod() = m and + this.asExpr() = ma.getQualifier() + ) + or + // calls to SocketFactory.createSocket with parameters immediately create the connection + exists(MethodAccess ma, Method m | + ma.getMethod() = m and + m instanceof CreateSocket and + m.getNumberOfParameters() > 0 + | + this.asExpr() = ma + ) + } +} + +/** + * An SSL object that was assigned a safe `SSLParameters` object an can be considered safe. + */ +class SslConnectionWithSafeSslParameters extends Expr { + SslConnectionWithSafeSslParameters() { + exists(SafeSslParametersFlowConfig config, DataFlow::Node safe | + config.hasFlowTo(safe) and this = safe.asExpr().(Argument).getCall().getQualifier() + ) + } +} + +private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { + SafeSslParametersFlowConfig() { this = "SafeSslParametersFlowConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(MethodAccess ma | + ma instanceof SafeSetEndpointIdentificationAlgorithm and + ma.getQualifier() = source.asExpr() + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma, RefType t | t instanceof SSLSocket or t instanceof SSLEngine | + ma.getMethod().hasName("setSSLParameters") and + ma.getMethod().getDeclaringType().getASupertype*() = t and + ma.getArgument(0) = sink.asExpr() + ) + } +} + +private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess { + SafeSetEndpointIdentificationAlgorithm() { + this.getMethod().hasName("setEndpointIdentificationAlgorithm") and + this.getMethod().getDeclaringType() instanceof SSLParameters and + not this.getArgument(0) instanceof NullLiteral and + not this.getArgument(0).(CompileTimeConstantExpr).getStringValue().length() = 0 + } +} + +/** + * A call to the method `useSslProtocol` on an instance of `com.rabbitmq.client.ConnectionFactory` + * that doesn't have `enableHostnameVerification` set. + */ +class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess { + RabbitMQEnableHostnameVerificationNotSet() { + this.getMethod().hasName("useSslProtocol") and + this.getMethod().getDeclaringType() instanceof RabbitMQConnectionFactory and + exists(Variable v | + v.getType() instanceof RabbitMQConnectionFactory and + this.getQualifier() = v.getAnAccess() and + not exists(MethodAccess ma | + ma.getMethod().hasName("enableHostnameVerification") and + ma.getQualifier() = v.getAnAccess() + ) + ) + } +} + +private class RabbitMQConnectionFactory extends RefType { + RabbitMQConnectionFactory() { this.hasQualifiedName("com.rabbitmq.client", "ConnectionFactory") } +} diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql index a86505606ca..b576e24d3c2 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -12,158 +12,25 @@ */ import java -import semmle.code.java.security.Encryption +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.security.UnsafeCertTrust -class SSLEngine extends RefType { - SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } -} +class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { + SslEndpointIdentificationFlowConfig() { this = "SslEndpointIdentificationFlowConfig" } -class Socket extends RefType { - Socket() { this.hasQualifiedName("java.net", "Socket") } -} + override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } -class SocketFactory extends RefType { - SocketFactory() { this.hasQualifiedName("javax.net", "SocketFactory") } -} + override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } -class SSLSocket extends RefType { - SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } -} - -/** - * has setEndpointIdentificationAlgorithm set correctly - */ -predicate setEndpointIdentificationAlgorithm(MethodAccess createSSL) { - exists( - Variable sslo, MethodAccess ma, Variable sslparams //setSSLParameters with valid setEndpointIdentificationAlgorithm set - | - createSSL = sslo.getAnAssignedValue() and - ma.getQualifier() = sslo.getAnAccess() and - ma.getMethod().hasName("setSSLParameters") and - ma.getArgument(0) = sslparams.getAnAccess() and - exists(MethodAccess setepa | - setepa.getQualifier() = sslparams.getAnAccess() and - setepa.getMethod().hasName("setEndpointIdentificationAlgorithm") and - not setepa.getArgument(0) instanceof NullLiteral - ) - ) -} - -/** - * has setEndpointIdentificationAlgorithm set correctly - */ -predicate hasEndpointIdentificationAlgorithm(Variable ssl) { - exists( - MethodAccess ma, Variable sslparams //setSSLParameters with valid setEndpointIdentificationAlgorithm set - | - ma.getQualifier() = ssl.getAnAccess() and - ma.getMethod().hasName("setSSLParameters") and - ma.getArgument(0) = sslparams.getAnAccess() and - exists(MethodAccess setepa | - setepa.getQualifier() = sslparams.getAnAccess() and - setepa.getMethod().hasName("setEndpointIdentificationAlgorithm") and - not setepa.getArgument(0) instanceof NullLiteral - ) - ) -} - -/** - * Cast of Socket to SSLSocket - */ -predicate sslCast(MethodAccess createSSL) { - exists(Variable ssl, CastExpr ce | - ce.getExpr() = createSSL and - ce.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl and - ssl.getType() instanceof SSLSocket //With a type cast `SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443)` - ) -} - -/** - * SSL object is created in a separate method call or in the same method - */ -predicate hasFlowPath(MethodAccess createSSL, Variable ssl) { - ( - createSSL = ssl.getAnAssignedValue() - or - exists(CastExpr ce | - ce.getExpr() = createSSL and - ce.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl //With a type cast like SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); - ) - ) - or - exists(MethodAccess tranm | - createSSL.getEnclosingCallable() = tranm.getMethod() and - tranm.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl and - not setEndpointIdentificationAlgorithm(createSSL) //Check the scenario of invocation before used in the current method - ) -} - -/** - * Not have the SSLParameter set - */ -predicate hasNoEndpointIdentificationSet(MethodAccess createSSL, Variable ssl) { - //No setSSLParameters set - hasFlowPath(createSSL, ssl) and - not exists(MethodAccess ma | - ma.getQualifier() = ssl.getAnAccess() and - ma.getMethod().hasName("setSSLParameters") - ) - or - //No endpointIdentificationAlgorithm set with setSSLParameters - hasFlowPath(createSSL, ssl) and - not setEndpointIdentificationAlgorithm(createSSL) -} - -/** - * The setEndpointIdentificationAlgorithm method of SSLParameters with the ssl engine or socket - */ -class SSLEndpointIdentificationNotSet extends MethodAccess { - SSLEndpointIdentificationNotSet() { - ( - this.getMethod().hasName("createSSLEngine") and - this.getMethod().getDeclaringType() instanceof SSLContext //createEngine method of SSLContext - or - this.getMethod().hasName("createSocket") and - this.getMethod().getDeclaringType() instanceof SocketFactory and - this.getMethod().getReturnType() instanceof Socket and - sslCast(this) //createSocket method of SocketFactory - ) and - exists(Variable ssl | - hasNoEndpointIdentificationSet(this, ssl) and //Not set in itself - not exists(VariableAssign ar, Variable newSsl | - ar.getSource() = this.getCaller().getAReference() and - ar.getDestVar() = newSsl and - hasEndpointIdentificationAlgorithm(newSsl) //Not set in its caller either - ) - ) and - not exists(MethodAccess ma | ma.getMethod() instanceof HostnameVerifierVerify) //Reduce false positives since this method access set default hostname verifier + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer.asExpr() instanceof SslConnectionWithSafeSslParameters } } -class RabbitMQConnectionFactory extends RefType { - RabbitMQConnectionFactory() { this.hasQualifiedName("com.rabbitmq.client", "ConnectionFactory") } -} - -/** - * The com.rabbitmq.client.ConnectionFactory useSslProtocol method access without enableHostnameVerification - */ -class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess { - RabbitMQEnableHostnameVerificationNotSet() { - this.getMethod().hasName("useSslProtocol") and - this.getMethod().getDeclaringType() instanceof RabbitMQConnectionFactory and - exists(Variable v | - v.getType() instanceof RabbitMQConnectionFactory and - this.getQualifier() = v.getAnAccess() and - not exists(MethodAccess ma | - ma.getMethod().hasName("enableHostnameVerification") and - ma.getQualifier() = v.getAnAccess() - ) - ) - } -} - -from MethodAccess aa +from Expr unsafeConfig where - aa instanceof SSLEndpointIdentificationNotSet or - aa instanceof RabbitMQEnableHostnameVerificationNotSet -select aa, "Unsafe configuration of trusted certificates" + unsafeConfig instanceof RabbitMQEnableHostnameVerificationNotSet or + exists(SslEndpointIdentificationFlowConfig config | + config.hasFlowTo(DataFlow::exprNode(unsafeConfig)) + ) +select unsafeConfig, "Unsafe configuration of trusted certificates" diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java index cb8b472eb8f..aae25353045 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -1,20 +1,12 @@ -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocket; +import java.net.InetSocketAddress; +import java.net.Socket; +import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -import java.net.Socket; -import javax.net.SocketFactory; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -//import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.ConnectionFactory; public class UnsafeCertTrustTest { @@ -27,6 +19,7 @@ public class UnsafeCertTrustTest { SSLParameters sslParameters = sslEngine.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm(null); sslEngine.setSSLParameters(sslParameters); + sslEngine.getSession(); } /** @@ -35,17 +28,97 @@ public class UnsafeCertTrustTest { public void testSSLEngineEndpointIdNotSet() throws java.security.NoSuchAlgorithmException { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); + sslEngine.getSession(); + } + + /** + * Test the endpoint identification of SSL engine is set to HTTPS + */ + public void testSSLEngineEndpointIdSafe() throws java.security.NoSuchAlgorithmException { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLEngine sslEngine = sslContext.createSSLEngine(); + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslEngine.setSSLParameters(sslParameters); + sslEngine.getSession(); } /** * Test the endpoint identification of SSL socket is not set */ - public void testSSLSocketEndpointIdNotSet() throws java.security.NoSuchAlgorithmException, java.io.IOException { + public void testSSLSocketImmediatelyConnects() + throws java.security.NoSuchAlgorithmException, java.io.IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); } + /** + * Test the endpoint identification of SSL socket is not set + */ + public void testSSLSocketEndpointIdNotSet() + throws java.security.NoSuchAlgorithmException, java.io.IOException { + SSLContext sslContext = SSLContext.getInstance("TLS"); + final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + socket.connect(new InetSocketAddress("www.example.com", 443)); + } + + /** + * Test the endpoint identification of SSL socket is set to null + */ + public void testSSLSocketEndpointIdSetNull() + throws java.security.NoSuchAlgorithmException, java.io.IOException { + SSLContext sslContext = SSLContext.getInstance("TLS"); + final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm(null); + socket.setSSLParameters(sslParameters); + socket.connect(new InetSocketAddress("www.example.com", 443)); + } + + /** + * Test the endpoint identification of SSL socket is set to empty + */ + public void testSSLSocketEndpointIdSetEmpty() + throws java.security.NoSuchAlgorithmException, java.io.IOException { + SSLContext sslContext = SSLContext.getInstance("TLS"); + final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm(""); + socket.setSSLParameters(sslParameters); + socket.connect(new InetSocketAddress("www.example.com", 443)); + } + + /** + * Test the endpoint identification of SSL socket is not set + */ + public void testSSLSocketEndpointIdAfterConnecting() + throws java.security.NoSuchAlgorithmException, java.io.IOException { + SSLContext sslContext = SSLContext.getInstance("TLS"); + final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + socket.setSSLParameters(sslParameters); + } + + /** + * Test the endpoint identification of SSL socket is not set + */ + public void testSSLSocketEndpointIdSafe() + throws java.security.NoSuchAlgorithmException, java.io.IOException { + SSLContext sslContext = SSLContext.getInstance("TLS"); + final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + socket.setSSLParameters(sslParameters); + socket.connect(new InetSocketAddress("www.example.com", 443)); + } + /** * Test the endpoint identification of regular socket is not set */ @@ -54,11 +127,20 @@ public class UnsafeCertTrustTest { Socket socket = socketFactory.createSocket("www.example.com", 80); } - // /** - // * Test the enableHostnameVerification of RabbitMQConnectionFactory is not set - // */ - // public void testEnableHostnameVerificationOfRabbitMQFactoryNotSet() { - // ConnectionFactory connectionFactory = new ConnectionFactory(); - // connectionFactory.useSslProtocol(); - // } + /** + * Test the enableHostnameVerification of RabbitMQConnectionFactory is not set + */ + public void testRabbitMQFactoryEnableHostnameVerificationNotSet() throws Exception { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.useSslProtocol(); + } + + /** + * Test the enableHostnameVerification of RabbitMQConnectionFactory is not set + */ + public void testRabbitMQFactorySafe() throws Exception { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.useSslProtocol(); + connectionFactory.enableHostnameVerification(); + } } diff --git a/java/ql/test/query-tests/security/CWE-273/options b/java/ql/test/query-tests/security/CWE-273/options new file mode 100644 index 00000000000..a97d4b5eeee --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-273/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/amqp-client-5.12.0 \ No newline at end of file diff --git a/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java new file mode 100644 index 00000000000..f02c88893aa --- /dev/null +++ b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java @@ -0,0 +1,223 @@ +// Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. +// +// This software, the RabbitMQ Java client library, is triple-licensed under the +// Mozilla Public License 2.0 ("MPL"), the GNU General Public License version 2 +// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see +// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +package com.rabbitmq.client; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.Predicate; +import static java.util.concurrent.TimeUnit.MINUTES; + +public class ConnectionFactory implements Cloneable { + public static final int DEFAULT_CHANNEL_RPC_TIMEOUT = (int) MINUTES.toMillis(10); + + public String getHost() { + return null; + } + + public void setHost(String host) {} + + public static int portOrDefault(int port, boolean ssl) { + return 0; + } + + public int getPort() { + return 0; + } + + public void setPort(int port) {} + + public String getUsername() { + return null; + } + + public void setUsername(String username) {} + + public String getPassword() { + return null; + } + + public void setPassword(String password) {} + + public String getVirtualHost() { + return null; + } + + public void setVirtualHost(String virtualHost) {} + + public void setUri(URI uri) + throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException {} + + public void setUri(String uriString) + throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException {} + + public int getRequestedChannelMax() { + return 0; + } + + public void setRequestedChannelMax(int requestedChannelMax) {} + + public int getRequestedFrameMax() { + return 0; + } + + public void setRequestedFrameMax(int requestedFrameMax) {} + + public int getRequestedHeartbeat() { + return 0; + } + + public void setConnectionTimeout(int timeout) {} + + public int getConnectionTimeout() { + return 0; + } + + public int getHandshakeTimeout() { + return 0; + } + + public void setHandshakeTimeout(int timeout) {} + + public void setShutdownTimeout(int shutdownTimeout) {} + + public int getShutdownTimeout() { + return 0; + } + + public void setRequestedHeartbeat(int requestedHeartbeat) {} + + public Map getClientProperties() { + return null; + } + + public void setClientProperties(Map clientProperties) {} + + public void setSharedExecutor(ExecutorService executor) {} + + public void setShutdownExecutor(ExecutorService executor) {} + + public void setHeartbeatExecutor(ScheduledExecutorService executor) {} + + public ThreadFactory getThreadFactory() { + return null; + } + + public void setThreadFactory(ThreadFactory threadFactory) {} + + public boolean isSSL() { + return false; + } + + public void useSslProtocol() throws NoSuchAlgorithmException, KeyManagementException {} + + public void useSslProtocol(String protocol) + throws NoSuchAlgorithmException, KeyManagementException {} + + public void useSslProtocol(String protocol, TrustManager trustManager) + throws NoSuchAlgorithmException, KeyManagementException {} + + public void useSslProtocol(SSLContext context) {} + + public void enableHostnameVerification() {} + + public static String computeDefaultTlsProtocol(String[] supportedProtocols) { + return null; + } + + public boolean isAutomaticRecoveryEnabled() { + return false; + } + + public void setAutomaticRecoveryEnabled(boolean automaticRecovery) {} + + public boolean isTopologyRecoveryEnabled() { + return false; + } + + public void setTopologyRecoveryEnabled(boolean topologyRecovery) {} + + public ExecutorService getTopologyRecoveryExecutor() { + return null; + } + + public void setTopologyRecoveryExecutor(final ExecutorService topologyRecoveryExecutor) {} + + public ConnectionFactory load(String propertyFileLocation) throws IOException { + return null; + } + + public ConnectionFactory load(String propertyFileLocation, String prefix) throws IOException { + return null; + } + + public ConnectionFactory load(Properties properties) { + return null; + } + + public ConnectionFactory load(Properties properties, String prefix) { + return null; + } + + public ConnectionFactory load(Map properties) { + return null; + } + + public ConnectionFactory load(Map properties, String prefix) { + return null; + } + + public long getNetworkRecoveryInterval() { + return 0; + } + + public void setNetworkRecoveryInterval(int networkRecoveryInterval) {} + + public void setNetworkRecoveryInterval(long networkRecoveryInterval) {} + + public void useNio() {} + + public void useBlockingIo() {} + + public void setChannelRpcTimeout(int channelRpcTimeout) {} + + public int getChannelRpcTimeout() { + return 0; + } + + public void setChannelShouldCheckRpcResponseType(boolean channelShouldCheckRpcResponseType) {} + + public boolean isChannelShouldCheckRpcResponseType() { + return false; + } + + public void setWorkPoolTimeout(int workPoolTimeout) {} + + public int getWorkPoolTimeout() { + return 0; + } + + public static int ensureUnsignedShort(int value) { + return 0; + } + +} From 02d0fa91889d5e34a451363dd2b790bc33aba5d6 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Tue, 22 Jun 2021 09:31:47 +0200 Subject: [PATCH 099/196] Minor changes in QLDocs and a sanitizer's type --- .../lib/semmle/code/java/security/UnsafeCertTrust.qll | 10 +++++++--- java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 4dfa16e2078..89232a1e0a9 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -8,6 +8,7 @@ private import semmle.code.java.dataflow.DataFlow2 /** * The creation of an object that prepares an SSL connection. + * This is a source for `SslEndpointIdentificationFlowConfig`. */ class SslConnectionInit extends DataFlow::Node { SslConnectionInit() { @@ -18,6 +19,7 @@ class SslConnectionInit extends DataFlow::Node { /** * A call to a method that establishes an SSL connection. + * This is a sink for `SslEndpointIdentificationFlowConfig`. */ class SslConnectionCreation extends DataFlow::Node { SslConnectionCreation() { @@ -41,12 +43,14 @@ class SslConnectionCreation extends DataFlow::Node { } /** - * An SSL object that was assigned a safe `SSLParameters` object an can be considered safe. + * An SSL object that was assigned a safe `SSLParameters` object and can be considered safe. + * This is a sanitizer for `SslEndpointIdentificationFlowConfig`. */ -class SslConnectionWithSafeSslParameters extends Expr { +class SslConnectionWithSafeSslParameters extends DataFlow::Node { SslConnectionWithSafeSslParameters() { exists(SafeSslParametersFlowConfig config, DataFlow::Node safe | - config.hasFlowTo(safe) and this = safe.asExpr().(Argument).getCall().getQualifier() + config.hasFlowTo(safe) and + this = DataFlow::exprNode(safe.asExpr().(Argument).getCall().getQualifier()) ) } } diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql index b576e24d3c2..93de3cca872 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -23,7 +23,7 @@ class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer.asExpr() instanceof SslConnectionWithSafeSslParameters + sanitizer instanceof SslConnectionWithSafeSslParameters } } From e43fff2d3026c10778969e6c68e83610af8f08fd Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Tue, 22 Jun 2021 10:08:26 +0200 Subject: [PATCH 100/196] Use InlineExpectationsTest --- .../code/java/security/UnsafeCertTrust.qll | 21 ++++++++-- .../Security/CWE/CWE-273/UnsafeCertTrust.ql | 8 ++-- .../security/CWE-273/UnsafeCertTrust.expected | 3 -- .../security/CWE-273/UnsafeCertTrust.qlref | 1 - .../CWE-273/UnsafeCertTrustTest.expected | 0 .../security/CWE-273/UnsafeCertTrustTest.java | 36 +++++++++--------- .../security/CWE-273/UnsafeCertTrustTest.ql | 38 +++++++++++++++++++ 7 files changed, 78 insertions(+), 29 deletions(-) delete mode 100644 java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.expected delete mode 100644 java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref create mode 100644 java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.expected create mode 100644 java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 89232a1e0a9..986472fa58b 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -34,8 +34,9 @@ class SslConnectionCreation extends DataFlow::Node { // calls to SocketFactory.createSocket with parameters immediately create the connection exists(MethodAccess ma, Method m | ma.getMethod() = m and - m instanceof CreateSocket and - m.getNumberOfParameters() > 0 + m instanceof CreateSocketMethod and + m.getNumberOfParameters() > 0 and + isSslSocket(ma) | this.asExpr() = ma ) @@ -55,6 +56,20 @@ class SslConnectionWithSafeSslParameters extends DataFlow::Node { } } +/** + * Holds if the return value of `createSocket` is cast to `SSLSocket` + * or the qualifier of `createSocket` is an instance of `SSLSocketFactory`. + */ +private predicate isSslSocket(MethodAccess createSocket) { + exists(Variable ssl, CastExpr ce | + ce.getExpr() = createSocket and + ce.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl and + ssl.getType() instanceof SSLSocket + ) + or + createSocket.getQualifier().getType().(RefType).getASupertype*() instanceof SSLSocketFactory +} + private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { SafeSslParametersFlowConfig() { this = "SafeSslParametersFlowConfig" } @@ -85,7 +100,7 @@ private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess { /** * A call to the method `useSslProtocol` on an instance of `com.rabbitmq.client.ConnectionFactory` - * that doesn't have `enableHostnameVerification` set. + * that doesn't set `enableHostnameVerification`. */ class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess { RabbitMQEnableHostnameVerificationNotSet() { diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql index 93de3cca872..8ab77389d36 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -27,10 +27,10 @@ class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { } } -from Expr unsafeConfig +from Expr unsafeTrust where - unsafeConfig instanceof RabbitMQEnableHostnameVerificationNotSet or + unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet or exists(SslEndpointIdentificationFlowConfig config | - config.hasFlowTo(DataFlow::exprNode(unsafeConfig)) + config.hasFlowTo(DataFlow::exprNode(unsafeTrust)) ) -select unsafeConfig, "Unsafe configuration of trusted certificates" +select unsafeTrust, "Unsafe configuration of trusted certificates" diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.expected b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.expected deleted file mode 100644 index f26706a56d2..00000000000 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.expected +++ /dev/null @@ -1,3 +0,0 @@ -| UnsafeCertTrustTest.java:26:25:26:52 | createSSLEngine(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:37:25:37:52 | createSSLEngine(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:46:34:46:83 | createSocket(...) | Unsafe configuration of trusted certificates | diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref deleted file mode 100644 index e63adf79e5e..00000000000 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrust.qlref +++ /dev/null @@ -1 +0,0 @@ -Security/CWE/CWE-273/UnsafeCertTrust.ql diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.expected b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java index aae25353045..6b65cda8868 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -19,7 +19,7 @@ public class UnsafeCertTrustTest { SSLParameters sslParameters = sslEngine.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm(null); sslEngine.setSSLParameters(sslParameters); - sslEngine.getSession(); + sslEngine.getSession(); // $hasUnsafeCertTrust } /** @@ -28,7 +28,7 @@ public class UnsafeCertTrustTest { public void testSSLEngineEndpointIdNotSet() throws java.security.NoSuchAlgorithmException { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); - sslEngine.getSession(); + sslEngine.getSession(); // $hasUnsafeCertTrust } /** @@ -40,7 +40,7 @@ public class UnsafeCertTrustTest { SSLParameters sslParameters = sslEngine.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); sslEngine.setSSLParameters(sslParameters); - sslEngine.getSession(); + sslEngine.getSession(); // Safe } /** @@ -49,8 +49,8 @@ public class UnsafeCertTrustTest { public void testSSLSocketImmediatelyConnects() throws java.security.NoSuchAlgorithmException, java.io.IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); - final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); - SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); + SocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); // $hasUnsafeCertTrust } /** @@ -59,9 +59,9 @@ public class UnsafeCertTrustTest { public void testSSLSocketEndpointIdNotSet() throws java.security.NoSuchAlgorithmException, java.io.IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); - final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); - socket.connect(new InetSocketAddress("www.example.com", 443)); + socket.connect(new InetSocketAddress("www.example.com", 443)); // $hasUnsafeCertTrust } /** @@ -70,12 +70,12 @@ public class UnsafeCertTrustTest { public void testSSLSocketEndpointIdSetNull() throws java.security.NoSuchAlgorithmException, java.io.IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); - final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm(null); socket.setSSLParameters(sslParameters); - socket.connect(new InetSocketAddress("www.example.com", 443)); + socket.connect(new InetSocketAddress("www.example.com", 443)); // $hasUnsafeCertTrust } /** @@ -84,12 +84,12 @@ public class UnsafeCertTrustTest { public void testSSLSocketEndpointIdSetEmpty() throws java.security.NoSuchAlgorithmException, java.io.IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); - final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm(""); socket.setSSLParameters(sslParameters); - socket.connect(new InetSocketAddress("www.example.com", 443)); + socket.connect(new InetSocketAddress("www.example.com", 443)); // $hasUnsafeCertTrust } /** @@ -98,8 +98,8 @@ public class UnsafeCertTrustTest { public void testSSLSocketEndpointIdAfterConnecting() throws java.security.NoSuchAlgorithmException, java.io.IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); - final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); - SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); // $hasUnsafeCertTrust SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); socket.setSSLParameters(sslParameters); @@ -111,12 +111,12 @@ public class UnsafeCertTrustTest { public void testSSLSocketEndpointIdSafe() throws java.security.NoSuchAlgorithmException, java.io.IOException { SSLContext sslContext = SSLContext.getInstance("TLS"); - final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); socket.setSSLParameters(sslParameters); - socket.connect(new InetSocketAddress("www.example.com", 443)); + socket.connect(new InetSocketAddress("www.example.com", 443)); // Safe } /** @@ -124,7 +124,7 @@ public class UnsafeCertTrustTest { */ public void testSocketEndpointIdNotSet() throws java.io.IOException { SocketFactory socketFactory = SocketFactory.getDefault(); - Socket socket = socketFactory.createSocket("www.example.com", 80); + Socket socket = socketFactory.createSocket("www.example.com", 80); // Safe } /** @@ -132,7 +132,7 @@ public class UnsafeCertTrustTest { */ public void testRabbitMQFactoryEnableHostnameVerificationNotSet() throws Exception { ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.useSslProtocol(); + connectionFactory.useSslProtocol(); // $hasUnsafeCertTrust } /** @@ -140,7 +140,7 @@ public class UnsafeCertTrustTest { */ public void testRabbitMQFactorySafe() throws Exception { ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.useSslProtocol(); + connectionFactory.useSslProtocol(); // Safe connectionFactory.enableHostnameVerification(); } } diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql new file mode 100644 index 00000000000..7abcbd0fd35 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql @@ -0,0 +1,38 @@ +import java +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.security.UnsafeCertTrust +import TestUtilities.InlineExpectationsTest + +class Conf extends TaintTracking::Configuration { + Conf() { this = "qltest:cwe:unsafe-cert-trust" } + + override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } + + override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer instanceof SslConnectionWithSafeSslParameters + } +} + +class UnsafeCertTrustTest extends InlineExpectationsTest { + UnsafeCertTrustTest() { this = "HasUnsafeCertTrustTest" } + + override string getARelevantTag() { result = "hasUnsafeCertTrust" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasUnsafeCertTrust" and + exists(Expr unsafeTrust | + unsafeTrust instanceof X509TrustAllManagerInit + or + unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet + or + exists(Conf config | config.hasFlowTo(DataFlow::exprNode(unsafeTrust))) + | + unsafeTrust.getLocation() = location and + element = unsafeTrust.toString() and + value = "" + ) + } +} From 5d4cd70f8cdc9877abb0cac828f2b16a74179e62 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Tue, 22 Jun 2021 17:53:15 +0200 Subject: [PATCH 101/196] Adjusted sources and sanitizer of UnsafeCertTrust taint tracking config --- .../semmle/code/java/security/Encryption.qll | 24 ++ .../code/java/security/UnsafeCertTrust.qll | 31 +- .../Security/CWE/CWE-273/UnsafeCertTrust.ql | 2 +- .../semmle/code/java/security/Encryption.qll | 373 ++++++++++++++++++ .../security/CWE-273/UnsafeCertTrustTest.java | 56 ++- .../security/CWE-273/UnsafeCertTrustTest.ql | 2 +- 6 files changed, 463 insertions(+), 25 deletions(-) create mode 100644 java/ql/src/semmle/code/java/security/Encryption.qll diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index 3ae5fdf3d9d..57c91d9cd55 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -122,6 +122,30 @@ class SetDefaultHostnameVerifierMethod extends Method { } } +/** The `beginHandshake` method of the class `javax.net.ssl.SSLEngine`. */ +class BeginHandshakeMethod extends Method { + BeginHandshakeMethod() { + this.hasName("beginHandshake") and + this.getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + +/** The `wrap` method of the class `javax.net.ssl.SSLEngine`. */ +class SslWrapMethod extends Method { + SslWrapMethod() { + this.hasName("wrap") and + this.getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + +/** The `unwrap` method of the class `javax.net.ssl.SSLEngine`. */ +class SslUnwrapMethod extends Method { + SslUnwrapMethod() { + this.hasName("unwrap") and + this.getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + /** The `getSession` method of the class `javax.net.ssl.SSLSession`.select */ class GetSslSessionMethod extends Method { GetSslSessionMethod() { diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 986472fa58b..64efc5130af 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -8,6 +8,7 @@ private import semmle.code.java.dataflow.DataFlow2 /** * The creation of an object that prepares an SSL connection. + * * This is a source for `SslEndpointIdentificationFlowConfig`. */ class SslConnectionInit extends DataFlow::Node { @@ -19,12 +20,15 @@ class SslConnectionInit extends DataFlow::Node { /** * A call to a method that establishes an SSL connection. + * * This is a sink for `SslEndpointIdentificationFlowConfig`. */ class SslConnectionCreation extends DataFlow::Node { SslConnectionCreation() { exists(MethodAccess ma, Method m | - m instanceof GetSslSessionMethod or + m instanceof BeginHandshakeMethod or + m instanceof SslWrapMethod or + m instanceof SslUnwrapMethod or m instanceof SocketConnectMethod | ma.getMethod() = m and @@ -44,10 +48,16 @@ class SslConnectionCreation extends DataFlow::Node { } /** - * An SSL object that was assigned a safe `SSLParameters` object and can be considered safe. + * An SSL object that correctly verifies hostnames, or doesn't need to (because e.g. it's a server). + * * This is a sanitizer for `SslEndpointIdentificationFlowConfig`. */ -class SslConnectionWithSafeSslParameters extends DataFlow::Node { +abstract class SslUnsafeCertTrustSanitizer extends DataFlow::Node { } + +/** + * An SSL object that was assigned a safe `SSLParameters` object and can be considered safe. + */ +private class SslConnectionWithSafeSslParameters extends SslUnsafeCertTrustSanitizer { SslConnectionWithSafeSslParameters() { exists(SafeSslParametersFlowConfig config, DataFlow::Node safe | config.hasFlowTo(safe) and @@ -56,6 +66,21 @@ class SslConnectionWithSafeSslParameters extends DataFlow::Node { } } +/** + * An `SSLEngine` set in server mode. + */ +private class SslEngineServerMode extends SslUnsafeCertTrustSanitizer { + SslEngineServerMode() { + exists(MethodAccess ma, Method m | + m.hasName("setUseClientMode") and + m.getDeclaringType().getASupertype*() instanceof SSLEngine and + ma.getMethod() = m and + ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = false and + this = DataFlow::exprNode(ma.getQualifier()) + ) + } +} + /** * Holds if the return value of `createSocket` is cast to `SSLSocket` * or the qualifier of `createSocket` is an instance of `SSLSocketFactory`. diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql index 8ab77389d36..2893329a4c3 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -23,7 +23,7 @@ class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer instanceof SslConnectionWithSafeSslParameters + sanitizer instanceof SslUnsafeCertTrustSanitizer } } diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll new file mode 100644 index 00000000000..05720974dea --- /dev/null +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -0,0 +1,373 @@ +/** + * Provides predicates and classes relating to encryption in Java. + */ + +import java + +class SSLClass extends RefType { + SSLClass() { + exists(Class c | this.getASupertype*() = c | + c.hasQualifiedName("javax.net.ssl", _) or + c.hasQualifiedName("javax.rmi.ssl", _) + ) + } +} + +class X509TrustManager extends RefType { + X509TrustManager() { this.hasQualifiedName("javax.net.ssl", "X509TrustManager") } +} + +class HttpsURLConnection extends RefType { + HttpsURLConnection() { hasQualifiedName("javax.net.ssl", "HttpsURLConnection") } +} + +class SSLSocketFactory extends RefType { + SSLSocketFactory() { this.hasQualifiedName("javax.net.ssl", "SSLSocketFactory") } +} + +class SSLContext extends RefType { + SSLContext() { hasQualifiedName("javax.net.ssl", "SSLContext") } +} + +/** The `javax.net.ssl.SSLSession` class. */ +class SSLSession extends RefType { + SSLSession() { hasQualifiedName("javax.net.ssl", "SSLSession") } +} + +class SSLEngine extends RefType { + SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } +} + +class SSLSocket extends RefType { + SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } +} + +/** The `javax.net.ssl.SSLParameters` class. */ +class SSLParameters extends RefType { + SSLParameters() { this.hasQualifiedName("javax.net.ssl", "SSLParameters") } +} + +class HostnameVerifier extends RefType { + HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") } +} + +/** The Java class `javax.crypto.KeyGenerator`. */ +class KeyGenerator extends RefType { + KeyGenerator() { this.hasQualifiedName("javax.crypto", "KeyGenerator") } +} + +/** The Java class `java.security.KeyPairGenerator`. */ +class KeyPairGenerator extends RefType { + KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") } +} + +/** The `verify` method of the class `javax.net.ssl.HostnameVerifier`. */ +class HostnameVerifierVerify extends Method { + HostnameVerifierVerify() { + hasName("verify") and + getDeclaringType().getASupertype*() instanceof HostnameVerifier and + getParameterType(0) instanceof TypeString and + getParameterType(1) instanceof SSLSession + } +} + +class TrustManagerCheckMethod extends Method { + TrustManagerCheckMethod() { + (this.hasName("checkClientTrusted") or this.hasName("checkServerTrusted")) and + this.getDeclaringType().getASupertype*() instanceof X509TrustManager + } +} + +class CreateSocket extends Method { + CreateSocket() { + hasName("createSocket") and + getDeclaringType() instanceof SSLSocketFactory + } +} + +class GetSocketFactory extends Method { + GetSocketFactory() { + hasName("getSocketFactory") and + getDeclaringType() instanceof SSLContext + } +} + +/** The `createSSLEngine` method of the class `javax.net.ssl.SSLContext` */ +class CreateSslEngineMethod extends Method { + CreateSslEngineMethod() { + this.hasName("createSSLEngine") and + this.getDeclaringType() instanceof SSLContext + } +} + +class SetConnectionFactoryMethod extends Method { + SetConnectionFactoryMethod() { + hasName("setSSLSocketFactory") and + getDeclaringType().getASupertype*() instanceof HttpsURLConnection + } +} + +class SetHostnameVerifierMethod extends Method { + SetHostnameVerifierMethod() { + hasName("setHostnameVerifier") and + getDeclaringType().getASupertype*() instanceof HttpsURLConnection + } +} + +/** The `setDefaultHostnameVerifier` method of the class `javax.net.ssl.HttpsURLConnection`. */ +class SetDefaultHostnameVerifierMethod extends Method { + SetDefaultHostnameVerifierMethod() { + hasName("setDefaultHostnameVerifier") and + getDeclaringType().getASupertype*() instanceof HttpsURLConnection + } +} + +/** The `beginHandshake` method of the class `javax.net.ssl.SSLEngine`. */ +class BeginHandshakeMethod extends Method { + BeginHandshakeMethod() { + hasName("beginHandshake") and + getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + +/** The `wrap` method of the class `javax.net.ssl.SSLEngine`. */ +class SslWrapMethod extends Method { + SslWrapMethod() { + hasName("wrap") and + getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + +/** The `unwrap` method of the class `javax.net.ssl.SSLEngine`. */ +class SslUnwrapMethod extends Method { + SslUnwrapMethod() { + hasName("unwrap") and + getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + +bindingset[algorithmString] +private string algorithmRegex(string algorithmString) { + // Algorithms usually appear in names surrounded by characters that are not + // alphabetical characters in the same case. This handles the upper and lower + // case cases. + result = + "((^|.*[^A-Z])(" + algorithmString + ")([^A-Z].*|$))" + + // or... + "|" + + // For lowercase, we want to be careful to avoid being confused by camelCase + // hence we require two preceding uppercase letters to be sure of a case switch, + // or a preceding non-alphabetic character + "((^|.*[A-Z]{2}|.*[^a-zA-Z])(" + algorithmString.toLowerCase() + ")([^a-z].*|$))" +} + +/** + * Gets the name of an algorithm that is known to be insecure. + */ +string getAnInsecureAlgorithmName() { + result = + [ + "DES", "RC2", "RC4", "RC5", + // ARCFOUR is a variant of RC4 + "ARCFOUR", + // Encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks + "ECB", + // CBC mode of operation with PKCS#5 or PKCS#7 padding is vulnerable to padding oracle attacks + "AES/CBC/PKCS[57]Padding" + ] +} + +/** + * Gets the name of a hash algorithm that is insecure if it is being used for + * encryption. + */ +string getAnInsecureHashAlgorithmName() { + result = "SHA1" or + result = "MD5" +} + +private string rankedInsecureAlgorithm(int i) { + // In this case we know these are being used for encryption, so we want to match + // weak hash algorithms too. + result = + rank[i](string s | s = getAnInsecureAlgorithmName() or s = getAnInsecureHashAlgorithmName()) +} + +private string insecureAlgorithmString(int i) { + i = 1 and result = rankedInsecureAlgorithm(i) + or + result = rankedInsecureAlgorithm(i) + "|" + insecureAlgorithmString(i - 1) +} + +/** + * Gets the regular expression used for matching strings that look like they + * contain an algorithm that is known to be insecure. + */ +string getInsecureAlgorithmRegex() { + result = algorithmRegex(insecureAlgorithmString(max(int i | exists(rankedInsecureAlgorithm(i))))) +} + +/** + * Gets the name of an algorithm that is known to be secure. + */ +string getASecureAlgorithmName() { + result = + [ + "RSA", "SHA256", "SHA512", "CCM", "GCM", "AES([^a-zA-Z](?!ECB|CBC/PKCS[57]Padding)).*", + "Blowfish", "ECIES" + ] +} + +private string rankedSecureAlgorithm(int i) { result = rank[i](getASecureAlgorithmName()) } + +private string secureAlgorithmString(int i) { + i = 1 and result = rankedSecureAlgorithm(i) + or + result = rankedSecureAlgorithm(i) + "|" + secureAlgorithmString(i - 1) +} + +/** + * Gets a regular expression for matching strings that look like they + * contain an algorithm that is known to be secure. + */ +string getSecureAlgorithmRegex() { + result = algorithmRegex(secureAlgorithmString(max(int i | exists(rankedSecureAlgorithm(i))))) +} + +/** + * DEPRECATED: Terminology has been updated. Use `getAnInsecureAlgorithmName()` + * instead. + */ +deprecated string algorithmBlacklist() { result = getAnInsecureAlgorithmName() } + +/** + * DEPRECATED: Terminology has been updated. Use + * `getAnInsecureHashAlgorithmName()` instead. + */ +deprecated string hashAlgorithmBlacklist() { result = getAnInsecureHashAlgorithmName() } + +/** + * DEPRECATED: Terminology has been updated. Use `getInsecureAlgorithmRegex()` instead. + */ +deprecated string algorithmBlacklistRegex() { result = getInsecureAlgorithmRegex() } + +/** + * DEPRECATED: Terminology has been updated. Use `getASecureAlgorithmName()` + * instead. + */ +deprecated string algorithmWhitelist() { result = getASecureAlgorithmName() } + +/** + * DEPRECATED: Terminology has been updated. Use `getSecureAlgorithmRegex()` instead. + */ +deprecated string algorithmWhitelistRegex() { result = getSecureAlgorithmRegex() } + +/** + * Any use of a cryptographic element that specifies an encryption + * algorithm. For example, methods returning ciphers, decryption methods, + * constructors of cipher classes, etc. + */ +abstract class CryptoAlgoSpec extends Top { + CryptoAlgoSpec() { this instanceof Call } + + abstract Expr getAlgoSpec(); +} + +abstract class JavaxCryptoAlgoSpec extends CryptoAlgoSpec { } + +class JavaxCryptoCipher extends JavaxCryptoAlgoSpec { + JavaxCryptoCipher() { + exists(Method m | m.getAReference() = this | + m.getDeclaringType().getQualifiedName() = "javax.crypto.Cipher" and + m.getName() = "getInstance" + ) + } + + override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } +} + +class JavaxCryptoSecretKey extends JavaxCryptoAlgoSpec { + JavaxCryptoSecretKey() { + exists(Constructor c | c.getAReference() = this | + c.getDeclaringType().getQualifiedName() = "javax.crypto.spec.SecretKeySpec" + ) + } + + override Expr getAlgoSpec() { + exists(ConstructorCall c | c = this | + if c.getNumArgument() = 2 then result = c.getArgument(1) else result = c.getArgument(3) + ) + } +} + +class JavaxCryptoKeyGenerator extends JavaxCryptoAlgoSpec { + JavaxCryptoKeyGenerator() { + exists(Method m | m.getAReference() = this | + m.getDeclaringType() instanceof KeyGenerator and + m.getName() = "getInstance" + ) + } + + override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } +} + +class JavaxCryptoKeyAgreement extends JavaxCryptoAlgoSpec { + JavaxCryptoKeyAgreement() { + exists(Method m | m.getAReference() = this | + m.getDeclaringType().getQualifiedName() = "javax.crypto.KeyAgreement" and + m.getName() = "getInstance" + ) + } + + override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } +} + +class JavaxCryptoKeyFactory extends JavaxCryptoAlgoSpec { + JavaxCryptoKeyFactory() { + exists(Method m | m.getAReference() = this | + m.getDeclaringType().getQualifiedName() = "javax.crypto.SecretKeyFactory" and + m.getName() = "getInstance" + ) + } + + override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } +} + +abstract class JavaSecurityAlgoSpec extends CryptoAlgoSpec { } + +class JavaSecurityMessageDigest extends JavaSecurityAlgoSpec { + JavaSecurityMessageDigest() { + exists(Constructor c | c.getAReference() = this | + c.getDeclaringType().hasQualifiedName("java.security", "MessageDigest") + ) + or + exists(Method m | m.getAReference() = this | + m.getDeclaringType().hasQualifiedName("java.security", "MessageDigest") and + m.getName() = "getInstance" + ) + } + + override Expr getAlgoSpec() { result = this.(Call).getArgument(0) } +} + +class JavaSecuritySignature extends JavaSecurityAlgoSpec { + JavaSecuritySignature() { + exists(Constructor c | c.getAReference() = this | + c.getDeclaringType().getQualifiedName() = "java.security.Signature" + ) + } + + override Expr getAlgoSpec() { result = this.(ConstructorCall).getArgument(0) } +} + +/** A method call to the Java class `java.security.KeyPairGenerator`. */ +class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec { + JavaSecurityKeyPairGenerator() { + exists(Method m | m.getAReference() = this | + m.getDeclaringType() instanceof KeyPairGenerator and + m.getName() = "getInstance" + ) + } + + override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } +} diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java index 6b65cda8868..181ce1d9a4f 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -1,5 +1,6 @@ import java.net.InetSocketAddress; import java.net.Socket; +import java.nio.ByteBuffer; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -13,41 +14,61 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL engine is set to null */ - public void testSSLEngineEndpointIdSetNull() throws java.security.NoSuchAlgorithmException { + public void testSSLEngineEndpointIdSetNull() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); SSLParameters sslParameters = sslEngine.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm(null); sslEngine.setSSLParameters(sslParameters); - sslEngine.getSession(); // $hasUnsafeCertTrust + sslEngine.beginHandshake(); // $hasUnsafeCertTrust + sslEngine.wrap(new ByteBuffer[] {}, null); // $hasUnsafeCertTrust + sslEngine.unwrap(null, null, 0, 0); // $hasUnsafeCertTrust } /** - * Test the endpoint identification of SSL engine is not set + * Test the endpoint identification of SSL engine is set to null */ - public void testSSLEngineEndpointIdNotSet() throws java.security.NoSuchAlgorithmException { + public void testSSLEngineEndpointIdSetEmpty() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); - sslEngine.getSession(); // $hasUnsafeCertTrust + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm(""); + sslEngine.setSSLParameters(sslParameters); + sslEngine.beginHandshake(); // $hasUnsafeCertTrust + sslEngine.wrap(new ByteBuffer[] {}, null); // $hasUnsafeCertTrust + sslEngine.unwrap(null, null, 0, 0); // $hasUnsafeCertTrust } /** * Test the endpoint identification of SSL engine is set to HTTPS */ - public void testSSLEngineEndpointIdSafe() throws java.security.NoSuchAlgorithmException { + public void testSSLEngineEndpointIdSafe() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); SSLParameters sslParameters = sslEngine.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); sslEngine.setSSLParameters(sslParameters); - sslEngine.getSession(); // Safe + sslEngine.beginHandshake(); // Safe + sslEngine.wrap(new ByteBuffer[] {}, null); // Safe + sslEngine.unwrap(null, null, 0, 0); // Safe + } + + /** + * Test the endpoint identification of SSL engine is set to HTTPS + */ + public void testSSLEngineInServerMode() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLEngine sslEngine = sslContext.createSSLEngine(); + sslEngine.setUseClientMode(false); + sslEngine.beginHandshake(); // Safe + sslEngine.wrap(new ByteBuffer[] {}, null); // Safe + sslEngine.unwrap(null, null, 0, 0); // Safe } /** * Test the endpoint identification of SSL socket is not set */ - public void testSSLSocketImmediatelyConnects() - throws java.security.NoSuchAlgorithmException, java.io.IOException { + public void testSSLSocketImmediatelyConnects() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); // $hasUnsafeCertTrust @@ -56,8 +77,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL socket is not set */ - public void testSSLSocketEndpointIdNotSet() - throws java.security.NoSuchAlgorithmException, java.io.IOException { + public void testSSLSocketEndpointIdNotSet() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); @@ -67,8 +87,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL socket is set to null */ - public void testSSLSocketEndpointIdSetNull() - throws java.security.NoSuchAlgorithmException, java.io.IOException { + public void testSSLSocketEndpointIdSetNull() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); @@ -81,8 +100,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL socket is set to empty */ - public void testSSLSocketEndpointIdSetEmpty() - throws java.security.NoSuchAlgorithmException, java.io.IOException { + public void testSSLSocketEndpointIdSetEmpty() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); @@ -95,8 +113,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL socket is not set */ - public void testSSLSocketEndpointIdAfterConnecting() - throws java.security.NoSuchAlgorithmException, java.io.IOException { + public void testSSLSocketEndpointIdAfterConnecting() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); // $hasUnsafeCertTrust @@ -108,8 +125,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of SSL socket is not set */ - public void testSSLSocketEndpointIdSafe() - throws java.security.NoSuchAlgorithmException, java.io.IOException { + public void testSSLSocketEndpointIdSafe() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); @@ -122,7 +138,7 @@ public class UnsafeCertTrustTest { /** * Test the endpoint identification of regular socket is not set */ - public void testSocketEndpointIdNotSet() throws java.io.IOException { + public void testSocketEndpointIdNotSet() throws Exception { SocketFactory socketFactory = SocketFactory.getDefault(); Socket socket = socketFactory.createSocket("www.example.com", 80); // Safe } diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql index 7abcbd0fd35..66a76175c65 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql @@ -12,7 +12,7 @@ class Conf extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer instanceof SslConnectionWithSafeSslParameters + sanitizer instanceof SslUnsafeCertTrustSanitizer } } From e842acf9e0da32247eb8cb5c3497f634af9207f1 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 23 Jun 2021 13:01:48 +0200 Subject: [PATCH 102/196] Improve qhelp --- .../src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp index ae8d76b1bb1..c317b9478de 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp @@ -4,26 +4,23 @@ -

    When SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.

    -

    Unsafe implementation of the interface X509TrustManager and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks.

    -

    This query checks whether setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.

    +

    Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (the later is checked by the java/insecure-hostname-verifier query). Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.

    +

    When SSLSocket or SSLEngine are created without a secure setEndpointIdentificationAlgorithm, hostname verification is disabled by default.

    +

    This query checks whether a trust manager is set to trust all certificates or setEndpointIdentificationAlgorithm is missing, thereby making the application vulnerable to man-in-the-middle attacks. The query also covers insecure configurations of com.rabbitmq.client.ConnectionFactory.

    -

    Validate SSL certificate in SSL authentication.

    +

    Validate SSL certificates in SSL authentication.

    The following two examples show two ways of configuring SSLSocket/SSLEngine. In the 'BAD' case, -setEndpointIdentificationAlgorithm is not called, thus no hostname verification takes place. In the 'GOOD' case, setEndpointIdentificationAlgorithm is called.

    +setEndpointIdentificationAlgorithm is not called, thus no hostname verification takes place. In the 'GOOD' case, setEndpointIdentificationAlgorithm is called.

  • -CWE-273 -
  • -
  • Testing Endpoint Identify Verification (MSTG-NETWORK-3)
  • From 4508945f85371bde2e31aee70d5fe741112cf1ae Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 23 Jun 2021 13:02:57 +0200 Subject: [PATCH 103/196] Fix assumption regarding when an SSLSocket does the TLS handhsake --- .../code/java/frameworks/Networking.qll | 10 +++- .../code/java/security/UnsafeCertTrust.qll | 22 +++---- .../security/CWE-273/UnsafeCertTrustTest.java | 57 +++---------------- 3 files changed, 26 insertions(+), 63 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/Networking.qll b/java/ql/lib/semmle/code/java/frameworks/Networking.qll index 7be77e26d64..c45b7036434 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Networking.qll @@ -47,6 +47,14 @@ class SocketGetInputStreamMethod extends Method { } } +class SocketGetOutputStreamMethod extends Method { + SocketGetOutputStreamMethod() { + this.getDeclaringType() instanceof TypeSocket and + this.hasName("getOutputStream") and + this.hasNoParameters() + } +} + /** A method or constructor call that returns a new `URI`. */ class UriCreation extends Call { UriCreation() { @@ -152,7 +160,7 @@ class UrlOpenConnectionMethod extends Method { class CreateSocketMethod extends Method { CreateSocketMethod() { this.hasName("createSocket") and - this.getDeclaringType() instanceof TypeSocketFactory + this.getDeclaringType().getASupertype*() instanceof TypeSocketFactory } } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 64efc5130af..bed35a1efa1 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -13,8 +13,14 @@ private import semmle.code.java.dataflow.DataFlow2 */ class SslConnectionInit extends DataFlow::Node { SslConnectionInit() { - this.asExpr().(MethodAccess).getMethod() instanceof CreateSslEngineMethod or - this.asExpr().(MethodAccess).getMethod() instanceof CreateSocketMethod + exists(MethodAccess ma, Method m | + this.asExpr() = ma and + ma.getMethod() = m + | + m instanceof CreateSslEngineMethod + or + m instanceof CreateSocketMethod and isSslSocket(ma) + ) } } @@ -29,21 +35,11 @@ class SslConnectionCreation extends DataFlow::Node { m instanceof BeginHandshakeMethod or m instanceof SslWrapMethod or m instanceof SslUnwrapMethod or - m instanceof SocketConnectMethod + m instanceof SocketGetOutputStreamMethod | ma.getMethod() = m and this.asExpr() = ma.getQualifier() ) - or - // calls to SocketFactory.createSocket with parameters immediately create the connection - exists(MethodAccess ma, Method m | - ma.getMethod() = m and - m instanceof CreateSocketMethod and - m.getNumberOfParameters() > 0 and - isSslSocket(ma) - | - this.asExpr() = ma - ) } } diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java index 181ce1d9a4f..df9da3527d3 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -1,4 +1,3 @@ -import java.net.InetSocketAddress; import java.net.Socket; import java.nio.ByteBuffer; import javax.net.SocketFactory; @@ -25,9 +24,6 @@ public class UnsafeCertTrustTest { sslEngine.unwrap(null, null, 0, 0); // $hasUnsafeCertTrust } - /** - * Test the endpoint identification of SSL engine is set to null - */ public void testSSLEngineEndpointIdSetEmpty() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); @@ -39,9 +35,6 @@ public class UnsafeCertTrustTest { sslEngine.unwrap(null, null, 0, 0); // $hasUnsafeCertTrust } - /** - * Test the endpoint identification of SSL engine is set to HTTPS - */ public void testSSLEngineEndpointIdSafe() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); @@ -53,9 +46,6 @@ public class UnsafeCertTrustTest { sslEngine.unwrap(null, null, 0, 0); // Safe } - /** - * Test the endpoint identification of SSL engine is set to HTTPS - */ public void testSSLEngineInServerMode() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLEngine sslEngine = sslContext.createSSLEngine(); @@ -65,28 +55,13 @@ public class UnsafeCertTrustTest { sslEngine.unwrap(null, null, 0, 0); // Safe } - /** - * Test the endpoint identification of SSL socket is not set - */ - public void testSSLSocketImmediatelyConnects() throws Exception { - SSLContext sslContext = SSLContext.getInstance("TLS"); - SocketFactory socketFactory = sslContext.getSocketFactory(); - SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); // $hasUnsafeCertTrust - } - - /** - * Test the endpoint identification of SSL socket is not set - */ public void testSSLSocketEndpointIdNotSet() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) socketFactory.createSocket(); - socket.connect(new InetSocketAddress("www.example.com", 443)); // $hasUnsafeCertTrust + socket.getOutputStream(); // $hasUnsafeCertTrust } - /** - * Test the endpoint identification of SSL socket is set to null - */ public void testSSLSocketEndpointIdSetNull() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); @@ -94,12 +69,9 @@ public class UnsafeCertTrustTest { SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm(null); socket.setSSLParameters(sslParameters); - socket.connect(new InetSocketAddress("www.example.com", 443)); // $hasUnsafeCertTrust + socket.getOutputStream(); // $hasUnsafeCertTrust } - /** - * Test the endpoint identification of SSL socket is set to empty - */ public void testSSLSocketEndpointIdSetEmpty() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); @@ -107,24 +79,19 @@ public class UnsafeCertTrustTest { SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm(""); socket.setSSLParameters(sslParameters); - socket.connect(new InetSocketAddress("www.example.com", 443)); // $hasUnsafeCertTrust + socket.getOutputStream(); // $hasUnsafeCertTrust } - /** - * Test the endpoint identification of SSL socket is not set - */ public void testSSLSocketEndpointIdAfterConnecting() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); - SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); // $hasUnsafeCertTrust + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + socket.getOutputStream(); // $hasUnsafeCertTrust SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); socket.setSSLParameters(sslParameters); } - /** - * Test the endpoint identification of SSL socket is not set - */ public void testSSLSocketEndpointIdSafe() throws Exception { SSLContext sslContext = SSLContext.getInstance("TLS"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); @@ -132,28 +99,20 @@ public class UnsafeCertTrustTest { SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); socket.setSSLParameters(sslParameters); - socket.connect(new InetSocketAddress("www.example.com", 443)); // Safe + socket.getOutputStream(); // Safe } - /** - * Test the endpoint identification of regular socket is not set - */ public void testSocketEndpointIdNotSet() throws Exception { SocketFactory socketFactory = SocketFactory.getDefault(); - Socket socket = socketFactory.createSocket("www.example.com", 80); // Safe + Socket socket = socketFactory.createSocket("www.example.com", 80); + socket.getOutputStream(); // Safe } - /** - * Test the enableHostnameVerification of RabbitMQConnectionFactory is not set - */ public void testRabbitMQFactoryEnableHostnameVerificationNotSet() throws Exception { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useSslProtocol(); // $hasUnsafeCertTrust } - /** - * Test the enableHostnameVerification of RabbitMQConnectionFactory is not set - */ public void testRabbitMQFactorySafe() throws Exception { ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.useSslProtocol(); // Safe From 64518bf91a32cb98bebe19ef9a049497400e9147 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 23 Jun 2021 15:43:48 +0200 Subject: [PATCH 104/196] Handle a specific pass-by-reference flow issue --- .../semmle/code/java/security/UnsafeCertTrust.qll | 2 +- .../security/CWE-273/UnsafeCertTrustTest.java | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index bed35a1efa1..2e3e2666933 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -97,7 +97,7 @@ private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { override predicate isSource(DataFlow::Node source) { exists(MethodAccess ma | ma instanceof SafeSetEndpointIdentificationAlgorithm and - ma.getQualifier() = source.asExpr() + DataFlow::getInstanceArgument(ma) = source.(DataFlow::PostUpdateNode).getPreUpdateNode() ) } diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java index df9da3527d3..6ac808b9623 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -102,6 +102,20 @@ public class UnsafeCertTrustTest { socket.getOutputStream(); // Safe } + public void testSSLSocketEndpointIdSafeWithModificationByReference() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + SSLParameters sslParameters = socket.getSSLParameters(); + onSetSSLParameters(sslParameters); + socket.setSSLParameters(sslParameters); + socket.getOutputStream(); // Safe + } + + private void onSetSSLParameters(SSLParameters sslParameters) { + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + } + public void testSocketEndpointIdNotSet() throws Exception { SocketFactory socketFactory = SocketFactory.getDefault(); Socket socket = socketFactory.createSocket("www.example.com", 80); From 19d1a780cabff7b9a0d2b8463f84ed7b42ebf679 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 23 Jun 2021 15:46:13 +0200 Subject: [PATCH 105/196] Generalize sanitizer using local flow --- .../semmle/code/java/security/UnsafeCertTrust.qll | 7 ++++--- .../security/CWE-273/UnsafeCertTrustTest.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 2e3e2666933..82e65c2fc87 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -55,9 +55,10 @@ abstract class SslUnsafeCertTrustSanitizer extends DataFlow::Node { } */ private class SslConnectionWithSafeSslParameters extends SslUnsafeCertTrustSanitizer { SslConnectionWithSafeSslParameters() { - exists(SafeSslParametersFlowConfig config, DataFlow::Node safe | + exists(SafeSslParametersFlowConfig config, DataFlow::Node safe, DataFlow::Node sanitizer | config.hasFlowTo(safe) and - this = DataFlow::exprNode(safe.asExpr().(Argument).getCall().getQualifier()) + sanitizer = DataFlow::exprNode(safe.asExpr().(Argument).getCall().getQualifier()) and + DataFlow::localFlow(sanitizer, this) ) } } @@ -72,7 +73,7 @@ private class SslEngineServerMode extends SslUnsafeCertTrustSanitizer { m.getDeclaringType().getASupertype*() instanceof SSLEngine and ma.getMethod() = m and ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = false and - this = DataFlow::exprNode(ma.getQualifier()) + this.asExpr() = ma.getQualifier() ) } } diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java index 6ac808b9623..84c5ff9048f 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -116,6 +116,18 @@ public class UnsafeCertTrustTest { sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); } + public void testSSLSocketEndpointIdSafeWithConditionalSanitizer(boolean safe) throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + if (safe) { + SSLParameters sslParameters = socket.getSSLParameters(); + onSetSSLParameters(sslParameters); + socket.setSSLParameters(sslParameters); + } + socket.getOutputStream(); // Safe + } + public void testSocketEndpointIdNotSet() throws Exception { SocketFactory socketFactory = SocketFactory.getDefault(); Socket socket = socketFactory.createSocket("www.example.com", 80); From 9e93aecf756f028336ba034bc1e17185882448bd Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 28 Jun 2021 12:16:41 +0200 Subject: [PATCH 106/196] Add spurious test case --- .../security/CWE-273/UnsafeCertTrustTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java index 84c5ff9048f..195b9142a4d 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -122,12 +122,23 @@ public class UnsafeCertTrustTest { SSLSocket socket = (SSLSocket) socketFactory.createSocket(); if (safe) { SSLParameters sslParameters = socket.getSSLParameters(); - onSetSSLParameters(sslParameters); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); socket.setSSLParameters(sslParameters); } socket.getOutputStream(); // Safe } + public void testSSLSocketEndpointIdSafeWithSanitizerInCast(boolean safe) throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + Socket socket = socketFactory.createSocket(); + SSLSocket sslSocket = (SSLSocket) socket; + SSLParameters sslParameters = sslSocket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslSocket.setSSLParameters(sslParameters); + socket.getOutputStream(); // $ SPURIOUS: hasUnsafeCertTrust + } + public void testSocketEndpointIdNotSet() throws Exception { SocketFactory socketFactory = SocketFactory.getDefault(); Socket socket = socketFactory.createSocket("www.example.com", 80); From 5997b874de9321b5c9f5d270322136191b99d6a0 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 28 Jun 2021 13:03:35 +0200 Subject: [PATCH 107/196] Add change note --- .../ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md diff --git a/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md b/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md new file mode 100644 index 00000000000..b9944f3a12b --- /dev/null +++ b/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* The query "Unsafe certificate trust" (`java/unsafe-cert-trust`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3550) \ No newline at end of file From c24520cb75d1e797a8e227476cdde528d8c16a49 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 28 Jun 2021 15:29:37 +0200 Subject: [PATCH 108/196] Adjust qhelp after rebase --- java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp index c317b9478de..3c76d429dbe 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp @@ -6,7 +6,7 @@

    Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (the later is checked by the java/insecure-hostname-verifier query). Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.

    When SSLSocket or SSLEngine are created without a secure setEndpointIdentificationAlgorithm, hostname verification is disabled by default.

    -

    This query checks whether a trust manager is set to trust all certificates or setEndpointIdentificationAlgorithm is missing, thereby making the application vulnerable to man-in-the-middle attacks. The query also covers insecure configurations of com.rabbitmq.client.ConnectionFactory.

    +

    This query checks whether setEndpointIdentificationAlgorithm is missing, thereby making the application vulnerable to man-in-the-middle attacks. The query also covers insecure configurations of com.rabbitmq.client.ConnectionFactory.

    From 68fe3dd9f4120598b5d42d8d89550087f49f38b7 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 28 Jun 2021 15:40:18 +0200 Subject: [PATCH 109/196] Fix conflicts in experimental query --- .../src/experimental/Security/CWE/CWE-327/SslLib.qll | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-327/SslLib.qll b/java/ql/src/experimental/Security/CWE/CWE-327/SslLib.qll index bfa2530b07e..7ca794220fb 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-327/SslLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-327/SslLib.qll @@ -94,18 +94,6 @@ class UnsafeTlsVersion extends StringLiteral { } } -class SSLParameters extends RefType { - SSLParameters() { hasQualifiedName("javax.net.ssl", "SSLParameters") } -} - -class SSLSocket extends RefType { - SSLSocket() { hasQualifiedName("javax.net.ssl", "SSLSocket") } -} - class SSLServerSocket extends RefType { SSLServerSocket() { hasQualifiedName("javax.net.ssl", "SSLServerSocket") } } - -class SSLEngine extends RefType { - SSLEngine() { hasQualifiedName("javax.net.ssl", "SSLEngine") } -} From 698fd64f7f9e72ad1cf7345435d2896966175fb1 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 28 Jun 2021 16:01:03 +0200 Subject: [PATCH 110/196] Adjust test after rebase --- .../ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql | 2 -- 1 file changed, 2 deletions(-) diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql index 66a76175c65..605e546d3d1 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql @@ -24,8 +24,6 @@ class UnsafeCertTrustTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasUnsafeCertTrust" and exists(Expr unsafeTrust | - unsafeTrust instanceof X509TrustAllManagerInit - or unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet or exists(Conf config | config.hasFlowTo(DataFlow::exprNode(unsafeTrust))) From e9712f04a435831e418f1e966a2d0f10e97dcb62 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Tue, 29 Jun 2021 14:30:45 +0200 Subject: [PATCH 111/196] Add missing QLDoc --- java/ql/src/semmle/code/java/security/Encryption.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll index 05720974dea..e8fab54fc73 100644 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ b/java/ql/src/semmle/code/java/security/Encryption.qll @@ -34,10 +34,12 @@ class SSLSession extends RefType { SSLSession() { hasQualifiedName("javax.net.ssl", "SSLSession") } } +/** The `javax.net.ssl.SSLEngine` class. */ class SSLEngine extends RefType { SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } } +/** The `javax.net.ssl.SSLSocket` class. */ class SSLSocket extends RefType { SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } } From 999acb00213b2b039a86035b6346d32c669403a8 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 1 Jul 2021 10:23:40 +0200 Subject: [PATCH 112/196] Improve qhelp references --- .../ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp index 3c76d429dbe..6dc4f14e044 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp @@ -23,6 +23,17 @@
  • Testing Endpoint Identify Verification (MSTG-NETWORK-3)
  • +
  • + SSLParameters.setEndpointIdentificationAlgorithm documentation +
  • +
  • + RabbitMQ: + ConnectionFactory.enableHostnameVerification documentation +
  • +
  • + RabbitMQ: + Using TLS in the Java Client +
  • CVE-2018-17187: Apache Qpid Proton-J transport issue with hostname verification
  • From 4d207101e274bdd0c62b82800be9623f01f4ee15 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 1 Jul 2021 10:30:42 +0200 Subject: [PATCH 113/196] Fix QLDoc --- java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 82e65c2fc87..2d7b8bf0c66 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -44,7 +44,7 @@ class SslConnectionCreation extends DataFlow::Node { } /** - * An SSL object that correctly verifies hostnames, or doesn't need to (because e.g. it's a server). + * An SSL object that correctly verifies hostnames, or doesn't need to (for instance, because it's a server). * * This is a sanitizer for `SslEndpointIdentificationFlowConfig`. */ From d9e98ceaccb028df29e759edf49f6e23958e46b9 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 1 Jul 2021 11:47:49 +0200 Subject: [PATCH 114/196] Consider setSslContextFactory and fix tests --- .../code/java/security/UnsafeCertTrust.qll | 6 +- .../security/CWE-273/UnsafeCertTrustTest.java | 38 +- .../rabbitmq/client/ConnectionFactory.java | 9 + .../rabbitmq/client/SslContextFactory.java | 23 + .../rabbitmq/client/ConnectionFactory.java | 410 ++++++++++++++++++ 5 files changed, 478 insertions(+), 8 deletions(-) create mode 100644 java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/SslContextFactory.java create mode 100644 java/ql/test/stubs/http-client-3.10.0/com/rabbitmq/client/ConnectionFactory.java diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 2d7b8bf0c66..64dd8dfe766 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -121,12 +121,12 @@ private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess { } /** - * A call to the method `useSslProtocol` on an instance of `com.rabbitmq.client.ConnectionFactory` - * that doesn't set `enableHostnameVerification`. + * A call to a method that enables SSL (`useSslProtocol` or `setSslContextFactory`) + * on an instance of `com.rabbitmq.client.ConnectionFactory` that doesn't set `enableHostnameVerification`. */ class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess { RabbitMQEnableHostnameVerificationNotSet() { - this.getMethod().hasName("useSslProtocol") and + this.getMethod().hasName(["useSslProtocol", "setSslContextFactory"]) and this.getMethod().getDeclaringType() instanceof RabbitMQConnectionFactory and exists(Variable v | v.getType() instanceof RabbitMQConnectionFactory and diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java index 195b9142a4d..5375c7c329e 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -1,5 +1,6 @@ import java.net.Socket; import java.nio.ByteBuffer; +import java.security.NoSuchAlgorithmException; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -7,6 +8,7 @@ import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.SslContextFactory; public class UnsafeCertTrustTest { @@ -146,13 +148,39 @@ public class UnsafeCertTrustTest { } public void testRabbitMQFactoryEnableHostnameVerificationNotSet() throws Exception { - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.useSslProtocol(); // $hasUnsafeCertTrust + { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.useSslProtocol(SSLContext.getDefault()); // $hasUnsafeCertTrust + } + { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setSslContextFactory(new TestSslContextFactory()); // $hasUnsafeCertTrust + } } public void testRabbitMQFactorySafe() throws Exception { - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.useSslProtocol(); // Safe - connectionFactory.enableHostnameVerification(); + { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.useSslProtocol(SSLContext.getDefault()); // Safe + connectionFactory.enableHostnameVerification(); + } + { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setSslContextFactory(new TestSslContextFactory()); // Safe + connectionFactory.enableHostnameVerification(); + } + } + + static class TestSslContextFactory implements SslContextFactory { + + @Override + public SSLContext create(String name) { + try { + return SSLContext.getDefault(); + } catch (NoSuchAlgorithmException e) { + return null; + } + } + } } diff --git a/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java index f02c88893aa..44dd5df1a26 100644 --- a/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java +++ b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java @@ -15,6 +15,7 @@ package com.rabbitmq.client; +import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import java.io.IOException; @@ -112,6 +113,12 @@ public class ConnectionFactory implements Cloneable { public void setClientProperties(Map clientProperties) {} + public SocketFactory getSocketFactory() { + return null; + } + + public void setSocketFactory(SocketFactory factory) {} + public void setSharedExecutor(ExecutorService executor) {} public void setShutdownExecutor(ExecutorService executor) {} @@ -204,6 +211,8 @@ public class ConnectionFactory implements Cloneable { return 0; } + public void setSslContextFactory(SslContextFactory sslContextFactory) {} + public void setChannelShouldCheckRpcResponseType(boolean channelShouldCheckRpcResponseType) {} public boolean isChannelShouldCheckRpcResponseType() { diff --git a/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/SslContextFactory.java b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/SslContextFactory.java new file mode 100644 index 00000000000..ae17f15437d --- /dev/null +++ b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/SslContextFactory.java @@ -0,0 +1,23 @@ +// Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. +// +// This software, the RabbitMQ Java client library, is triple-licensed under the +// Mozilla Public License 2.0 ("MPL"), the GNU General Public License version 2 +// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see +// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +package com.rabbitmq.client; + +import javax.net.ssl.SSLContext; + +public interface SslContextFactory { + SSLContext create(String name); + +} diff --git a/java/ql/test/stubs/http-client-3.10.0/com/rabbitmq/client/ConnectionFactory.java b/java/ql/test/stubs/http-client-3.10.0/com/rabbitmq/client/ConnectionFactory.java new file mode 100644 index 00000000000..90698f2edfa --- /dev/null +++ b/java/ql/test/stubs/http-client-3.10.0/com/rabbitmq/client/ConnectionFactory.java @@ -0,0 +1,410 @@ +// Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. +// +// This software, the RabbitMQ Java client library, is triple-licensed under the +// Mozilla Public License 2.0 ("MPL"), the GNU General Public License version 2 +// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see +// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +package com.rabbitmq.client; +import com.rabbitmq.client.impl.*; +import com.rabbitmq.client.impl.nio.NioParams; +import com.rabbitmq.client.impl.recovery.RetryHandler; +import com.rabbitmq.client.impl.recovery.TopologyRecoveryFilter; +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.Predicate; +import static java.util.concurrent.TimeUnit.MINUTES; + +public class ConnectionFactory implements Cloneable { + public static final int DEFAULT_CHANNEL_RPC_TIMEOUT = (int) MINUTES.toMillis(10); + + public String getHost() { + return null; + } + + public void setHost(String host) { + } + + public static int portOrDefault(int port, boolean ssl) { + return 0; + } + + public int getPort() { + return 0; + } + + public void setPort(int port) { + } + + public String getUsername() { + return null; + } + + public void setUsername(String username) { + } + + public String getPassword() { + return null; + } + + public void setPassword(String password) { + } + + public void setCredentialsProvider(CredentialsProvider credentialsProvider) { + } + + public String getVirtualHost() { + return null; + } + + public void setVirtualHost(String virtualHost) { + } + + public void setUri(URI uri) + throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException + { + } + + public void setUri(String uriString) + throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException + { + } + + public int getRequestedChannelMax() { + return 0; + } + + public void setRequestedChannelMax(int requestedChannelMax) { + } + + public int getRequestedFrameMax() { + return 0; + } + + public void setRequestedFrameMax(int requestedFrameMax) { + } + + public int getRequestedHeartbeat() { + return 0; + } + + public void setConnectionTimeout(int timeout) { + } + + public int getConnectionTimeout() { + return 0; + } + + public int getHandshakeTimeout() { + return 0; + } + + public void setHandshakeTimeout(int timeout) { + } + + public void setShutdownTimeout(int shutdownTimeout) { + } + + public int getShutdownTimeout() { + return 0; + } + + public void setRequestedHeartbeat(int requestedHeartbeat) { + } + + public Map getClientProperties() { + return null; + } + + public void setClientProperties(Map clientProperties) { + } + + public SaslConfig getSaslConfig() { + return null; + } + + public void setSaslConfig(SaslConfig saslConfig) { + } + + public SocketFactory getSocketFactory() { + return null; + } + + public void setSocketFactory(SocketFactory factory) { + } + + public SocketConfigurator getSocketConfigurator() { + return null; + } + + public void setSocketConfigurator(SocketConfigurator socketConfigurator) { + } + + public void setSharedExecutor(ExecutorService executor) { + } + + public void setShutdownExecutor(ExecutorService executor) { + } + + public void setHeartbeatExecutor(ScheduledExecutorService executor) { + } + + public ThreadFactory getThreadFactory() { + return null; + } + + public void setThreadFactory(ThreadFactory threadFactory) { + } + + public ExceptionHandler getExceptionHandler() { + return null; + } + + public void setExceptionHandler(ExceptionHandler exceptionHandler) { + } + + public boolean isSSL(){ + return false; + } + + public void useSslProtocol() + throws NoSuchAlgorithmException, KeyManagementException + { + } + + public void useSslProtocol(String protocol) + throws NoSuchAlgorithmException, KeyManagementException + { + } + + public void useSslProtocol(String protocol, TrustManager trustManager) + throws NoSuchAlgorithmException, KeyManagementException + { + } + + public void useSslProtocol(SSLContext context) { + } + + public void enableHostnameVerification() { + } + + public static String computeDefaultTlsProtocol(String[] supportedProtocols) { + return null; + } + + public boolean isAutomaticRecoveryEnabled() { + return false; + } + + public void setAutomaticRecoveryEnabled(boolean automaticRecovery) { + } + + public boolean isTopologyRecoveryEnabled() { + return false; + } + + public void setTopologyRecoveryEnabled(boolean topologyRecovery) { + } + + public ExecutorService getTopologyRecoveryExecutor() { + return null; + } + + public void setTopologyRecoveryExecutor(final ExecutorService topologyRecoveryExecutor) { + } + + public void setMetricsCollector(MetricsCollector metricsCollector) { + } + + public MetricsCollector getMetricsCollector() { + return null; + } + + public void setCredentialsRefreshService(CredentialsRefreshService credentialsRefreshService) { + } + + public Connection newConnection(Address[] addrs) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(AddressResolver addressResolver) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(Address[] addrs, String clientProvidedName) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(List
    addrs) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(List
    addrs, String clientProvidedName) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(ExecutorService executor, Address[] addrs) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(ExecutorService executor, Address[] addrs, String clientProvidedName) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(ExecutorService executor, List
    addrs) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(ExecutorService executor, AddressResolver addressResolver) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(ExecutorService executor, List
    addrs, String clientProvidedName) + throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(ExecutorService executor, AddressResolver addressResolver, String clientProvidedName) + throws IOException, TimeoutException { + return null; + } + + public ConnectionParams params(ExecutorService consumerWorkServiceExecutor) { + return null; + } + + public Connection newConnection() throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(String connectionName) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(ExecutorService executor) throws IOException, TimeoutException { + return null; + } + + public Connection newConnection(ExecutorService executor, String connectionName) throws IOException, TimeoutException { + return null; + } + + @Override public ConnectionFactory clone(){ + @Override public ConnectionFactory clone(){ + return null; + } + + public ConnectionFactory load(String propertyFileLocation) throws IOException { + return null; + } + + public ConnectionFactory load(String propertyFileLocation, String prefix) throws IOException { + return null; + } + + public ConnectionFactory load(Properties properties) { + return null; + } + + public ConnectionFactory load(Properties properties, String prefix) { + return null; + } + + public ConnectionFactory load(Map properties) { + return null; + } + + public ConnectionFactory load(Map properties, String prefix) { + return null; + } + + public long getNetworkRecoveryInterval() { + return 0; + } + + public void setNetworkRecoveryInterval(int networkRecoveryInterval) { + } + + public void setNetworkRecoveryInterval(long networkRecoveryInterval) { + } + + public RecoveryDelayHandler getRecoveryDelayHandler() { + return null; + } + + public void setRecoveryDelayHandler(final RecoveryDelayHandler recoveryDelayHandler) { + } + + public void setNioParams(NioParams nioParams) { + } + + public NioParams getNioParams() { + return null; + } + + public void useNio() { + } + + public void useBlockingIo() { + } + + public void setChannelRpcTimeout(int channelRpcTimeout) { + } + + public int getChannelRpcTimeout() { + return 0; + } + + public void setSslContextFactory(SslContextFactory sslContextFactory) { + } + + public void setChannelShouldCheckRpcResponseType(boolean channelShouldCheckRpcResponseType) { + } + + public boolean isChannelShouldCheckRpcResponseType() { + return false; + } + + public void setWorkPoolTimeout(int workPoolTimeout) { + } + + public int getWorkPoolTimeout() { + return 0; + } + + public void setErrorOnWriteListener(ErrorOnWriteListener errorOnWriteListener) { + } + + public void setTopologyRecoveryFilter(TopologyRecoveryFilter topologyRecoveryFilter) { + } + + public void setConnectionRecoveryTriggeringCondition(Predicate connectionRecoveryTriggeringCondition) { + } + + public void setTopologyRecoveryRetryHandler(RetryHandler topologyRecoveryRetryHandler) { + } + + public void setTrafficListener(TrafficListener trafficListener) { + } + + public static int ensureUnsignedShort(int value) { + return 0; + } + +} From 1e2a956a30afb263feb699b0f6729f79b18b7890 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 1 Jul 2021 15:11:54 +0200 Subject: [PATCH 115/196] Remove unused stub --- .../rabbitmq/client/ConnectionFactory.java | 410 ------------------ 1 file changed, 410 deletions(-) delete mode 100644 java/ql/test/stubs/http-client-3.10.0/com/rabbitmq/client/ConnectionFactory.java diff --git a/java/ql/test/stubs/http-client-3.10.0/com/rabbitmq/client/ConnectionFactory.java b/java/ql/test/stubs/http-client-3.10.0/com/rabbitmq/client/ConnectionFactory.java deleted file mode 100644 index 90698f2edfa..00000000000 --- a/java/ql/test/stubs/http-client-3.10.0/com/rabbitmq/client/ConnectionFactory.java +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. -// -// This software, the RabbitMQ Java client library, is triple-licensed under the -// Mozilla Public License 2.0 ("MPL"), the GNU General Public License version 2 -// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see -// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, -// please see LICENSE-APACHE2. -// -// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, -// either express or implied. See the LICENSE file for specific language governing -// rights and limitations of this software. -// -// If you have any questions regarding licensing, please contact us at -// info@rabbitmq.com. - -package com.rabbitmq.client; -import com.rabbitmq.client.impl.*; -import com.rabbitmq.client.impl.nio.NioParams; -import com.rabbitmq.client.impl.recovery.RetryHandler; -import com.rabbitmq.client.impl.recovery.TopologyRecoveryFilter; -import javax.net.SocketFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.util.*; -import java.util.concurrent.*; -import java.util.function.Predicate; -import static java.util.concurrent.TimeUnit.MINUTES; - -public class ConnectionFactory implements Cloneable { - public static final int DEFAULT_CHANNEL_RPC_TIMEOUT = (int) MINUTES.toMillis(10); - - public String getHost() { - return null; - } - - public void setHost(String host) { - } - - public static int portOrDefault(int port, boolean ssl) { - return 0; - } - - public int getPort() { - return 0; - } - - public void setPort(int port) { - } - - public String getUsername() { - return null; - } - - public void setUsername(String username) { - } - - public String getPassword() { - return null; - } - - public void setPassword(String password) { - } - - public void setCredentialsProvider(CredentialsProvider credentialsProvider) { - } - - public String getVirtualHost() { - return null; - } - - public void setVirtualHost(String virtualHost) { - } - - public void setUri(URI uri) - throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException - { - } - - public void setUri(String uriString) - throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException - { - } - - public int getRequestedChannelMax() { - return 0; - } - - public void setRequestedChannelMax(int requestedChannelMax) { - } - - public int getRequestedFrameMax() { - return 0; - } - - public void setRequestedFrameMax(int requestedFrameMax) { - } - - public int getRequestedHeartbeat() { - return 0; - } - - public void setConnectionTimeout(int timeout) { - } - - public int getConnectionTimeout() { - return 0; - } - - public int getHandshakeTimeout() { - return 0; - } - - public void setHandshakeTimeout(int timeout) { - } - - public void setShutdownTimeout(int shutdownTimeout) { - } - - public int getShutdownTimeout() { - return 0; - } - - public void setRequestedHeartbeat(int requestedHeartbeat) { - } - - public Map getClientProperties() { - return null; - } - - public void setClientProperties(Map clientProperties) { - } - - public SaslConfig getSaslConfig() { - return null; - } - - public void setSaslConfig(SaslConfig saslConfig) { - } - - public SocketFactory getSocketFactory() { - return null; - } - - public void setSocketFactory(SocketFactory factory) { - } - - public SocketConfigurator getSocketConfigurator() { - return null; - } - - public void setSocketConfigurator(SocketConfigurator socketConfigurator) { - } - - public void setSharedExecutor(ExecutorService executor) { - } - - public void setShutdownExecutor(ExecutorService executor) { - } - - public void setHeartbeatExecutor(ScheduledExecutorService executor) { - } - - public ThreadFactory getThreadFactory() { - return null; - } - - public void setThreadFactory(ThreadFactory threadFactory) { - } - - public ExceptionHandler getExceptionHandler() { - return null; - } - - public void setExceptionHandler(ExceptionHandler exceptionHandler) { - } - - public boolean isSSL(){ - return false; - } - - public void useSslProtocol() - throws NoSuchAlgorithmException, KeyManagementException - { - } - - public void useSslProtocol(String protocol) - throws NoSuchAlgorithmException, KeyManagementException - { - } - - public void useSslProtocol(String protocol, TrustManager trustManager) - throws NoSuchAlgorithmException, KeyManagementException - { - } - - public void useSslProtocol(SSLContext context) { - } - - public void enableHostnameVerification() { - } - - public static String computeDefaultTlsProtocol(String[] supportedProtocols) { - return null; - } - - public boolean isAutomaticRecoveryEnabled() { - return false; - } - - public void setAutomaticRecoveryEnabled(boolean automaticRecovery) { - } - - public boolean isTopologyRecoveryEnabled() { - return false; - } - - public void setTopologyRecoveryEnabled(boolean topologyRecovery) { - } - - public ExecutorService getTopologyRecoveryExecutor() { - return null; - } - - public void setTopologyRecoveryExecutor(final ExecutorService topologyRecoveryExecutor) { - } - - public void setMetricsCollector(MetricsCollector metricsCollector) { - } - - public MetricsCollector getMetricsCollector() { - return null; - } - - public void setCredentialsRefreshService(CredentialsRefreshService credentialsRefreshService) { - } - - public Connection newConnection(Address[] addrs) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(AddressResolver addressResolver) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(Address[] addrs, String clientProvidedName) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(List
    addrs) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(List
    addrs, String clientProvidedName) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(ExecutorService executor, Address[] addrs) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(ExecutorService executor, Address[] addrs, String clientProvidedName) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(ExecutorService executor, List
    addrs) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(ExecutorService executor, AddressResolver addressResolver) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(ExecutorService executor, List
    addrs, String clientProvidedName) - throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(ExecutorService executor, AddressResolver addressResolver, String clientProvidedName) - throws IOException, TimeoutException { - return null; - } - - public ConnectionParams params(ExecutorService consumerWorkServiceExecutor) { - return null; - } - - public Connection newConnection() throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(String connectionName) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(ExecutorService executor) throws IOException, TimeoutException { - return null; - } - - public Connection newConnection(ExecutorService executor, String connectionName) throws IOException, TimeoutException { - return null; - } - - @Override public ConnectionFactory clone(){ - @Override public ConnectionFactory clone(){ - return null; - } - - public ConnectionFactory load(String propertyFileLocation) throws IOException { - return null; - } - - public ConnectionFactory load(String propertyFileLocation, String prefix) throws IOException { - return null; - } - - public ConnectionFactory load(Properties properties) { - return null; - } - - public ConnectionFactory load(Properties properties, String prefix) { - return null; - } - - public ConnectionFactory load(Map properties) { - return null; - } - - public ConnectionFactory load(Map properties, String prefix) { - return null; - } - - public long getNetworkRecoveryInterval() { - return 0; - } - - public void setNetworkRecoveryInterval(int networkRecoveryInterval) { - } - - public void setNetworkRecoveryInterval(long networkRecoveryInterval) { - } - - public RecoveryDelayHandler getRecoveryDelayHandler() { - return null; - } - - public void setRecoveryDelayHandler(final RecoveryDelayHandler recoveryDelayHandler) { - } - - public void setNioParams(NioParams nioParams) { - } - - public NioParams getNioParams() { - return null; - } - - public void useNio() { - } - - public void useBlockingIo() { - } - - public void setChannelRpcTimeout(int channelRpcTimeout) { - } - - public int getChannelRpcTimeout() { - return 0; - } - - public void setSslContextFactory(SslContextFactory sslContextFactory) { - } - - public void setChannelShouldCheckRpcResponseType(boolean channelShouldCheckRpcResponseType) { - } - - public boolean isChannelShouldCheckRpcResponseType() { - return false; - } - - public void setWorkPoolTimeout(int workPoolTimeout) { - } - - public int getWorkPoolTimeout() { - return 0; - } - - public void setErrorOnWriteListener(ErrorOnWriteListener errorOnWriteListener) { - } - - public void setTopologyRecoveryFilter(TopologyRecoveryFilter topologyRecoveryFilter) { - } - - public void setConnectionRecoveryTriggeringCondition(Predicate connectionRecoveryTriggeringCondition) { - } - - public void setTopologyRecoveryRetryHandler(RetryHandler topologyRecoveryRetryHandler) { - } - - public void setTrafficListener(TrafficListener trafficListener) { - } - - public static int ensureUnsignedShort(int value) { - return 0; - } - -} From 000a5447298416ddd5e3d843e1a4f123d9077ca2 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 21 Jul 2021 11:29:49 +0200 Subject: [PATCH 116/196] Decouple UnsafeCertTrust.qll to reuse the taint tracking configuration --- .../code/java/security/UnsafeCertTrust.qll | 42 ------------- .../Security/CWE/CWE-273/UnsafeCertTrust.ql | 15 +---- .../2021-06-28-unsafe-cert-trust-query.md | 2 +- .../java/security/UnsafeCertTrustQuery.qll | 62 +++++++++++++++++++ .../security/CWE-273/UnsafeCertTrustTest.ql | 20 ++---- 5 files changed, 68 insertions(+), 73 deletions(-) create mode 100644 java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 64dd8dfe766..55c278a173c 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -4,7 +4,6 @@ import java private import semmle.code.java.frameworks.Networking private import semmle.code.java.security.Encryption private import semmle.code.java.dataflow.DataFlow -private import semmle.code.java.dataflow.DataFlow2 /** * The creation of an object that prepares an SSL connection. @@ -50,19 +49,6 @@ class SslConnectionCreation extends DataFlow::Node { */ abstract class SslUnsafeCertTrustSanitizer extends DataFlow::Node { } -/** - * An SSL object that was assigned a safe `SSLParameters` object and can be considered safe. - */ -private class SslConnectionWithSafeSslParameters extends SslUnsafeCertTrustSanitizer { - SslConnectionWithSafeSslParameters() { - exists(SafeSslParametersFlowConfig config, DataFlow::Node safe, DataFlow::Node sanitizer | - config.hasFlowTo(safe) and - sanitizer = DataFlow::exprNode(safe.asExpr().(Argument).getCall().getQualifier()) and - DataFlow::localFlow(sanitizer, this) - ) - } -} - /** * An `SSLEngine` set in server mode. */ @@ -92,34 +78,6 @@ private predicate isSslSocket(MethodAccess createSocket) { createSocket.getQualifier().getType().(RefType).getASupertype*() instanceof SSLSocketFactory } -private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { - SafeSslParametersFlowConfig() { this = "SafeSslParametersFlowConfig" } - - override predicate isSource(DataFlow::Node source) { - exists(MethodAccess ma | - ma instanceof SafeSetEndpointIdentificationAlgorithm and - DataFlow::getInstanceArgument(ma) = source.(DataFlow::PostUpdateNode).getPreUpdateNode() - ) - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodAccess ma, RefType t | t instanceof SSLSocket or t instanceof SSLEngine | - ma.getMethod().hasName("setSSLParameters") and - ma.getMethod().getDeclaringType().getASupertype*() = t and - ma.getArgument(0) = sink.asExpr() - ) - } -} - -private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess { - SafeSetEndpointIdentificationAlgorithm() { - this.getMethod().hasName("setEndpointIdentificationAlgorithm") and - this.getMethod().getDeclaringType() instanceof SSLParameters and - not this.getArgument(0) instanceof NullLiteral and - not this.getArgument(0).(CompileTimeConstantExpr).getStringValue().length() = 0 - } -} - /** * A call to a method that enables SSL (`useSslProtocol` or `setSslContextFactory`) * on an instance of `com.rabbitmq.client.ConnectionFactory` that doesn't set `enableHostnameVerification`. diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql index 2893329a4c3..12f20b40c93 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -12,20 +12,7 @@ */ import java -import semmle.code.java.dataflow.TaintTracking -import semmle.code.java.security.UnsafeCertTrust - -class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { - SslEndpointIdentificationFlowConfig() { this = "SslEndpointIdentificationFlowConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } - - override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } - - override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer instanceof SslUnsafeCertTrustSanitizer - } -} +import semmle.code.java.security.UnsafeCertTrustQuery from Expr unsafeTrust where diff --git a/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md b/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md index b9944f3a12b..bde0c9d0249 100644 --- a/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md +++ b/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md @@ -1,4 +1,4 @@ --- category: newQuery --- -* The query "Unsafe certificate trust" (`java/unsafe-cert-trust`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3550) \ No newline at end of file +* The query "Unsafe certificate trust" (`java/unsafe-cert-trust`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3550). diff --git a/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll new file mode 100644 index 00000000000..61f890a1d47 --- /dev/null +++ b/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll @@ -0,0 +1,62 @@ +/** Provides taint tracking configurations to be used by unsafe certificate trust queries. */ + +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.security.UnsafeCertTrust +import semmle.code.java.security.Encryption + +class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { + SslEndpointIdentificationFlowConfig() { this = "SslEndpointIdentificationFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } + + override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer instanceof SslUnsafeCertTrustSanitizer + } +} + +/** + * An SSL object that was assigned a safe `SSLParameters` object and can be considered safe. + */ +private class SslConnectionWithSafeSslParameters extends SslUnsafeCertTrustSanitizer { + SslConnectionWithSafeSslParameters() { + exists(SafeSslParametersFlowConfig config, DataFlow::Node safe, DataFlow::Node sanitizer | + config.hasFlowTo(safe) and + sanitizer = DataFlow::exprNode(safe.asExpr().(Argument).getCall().getQualifier()) and + DataFlow::localFlow(sanitizer, this) + ) + } +} + +private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { + SafeSslParametersFlowConfig() { this = "SafeSslParametersFlowConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(MethodAccess ma | + ma instanceof SafeSetEndpointIdentificationAlgorithm and + DataFlow::getInstanceArgument(ma) = source.(DataFlow::PostUpdateNode).getPreUpdateNode() + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma, RefType t | t instanceof SSLSocket or t instanceof SSLEngine | + ma.getMethod().hasName("setSSLParameters") and + ma.getMethod().getDeclaringType().getASupertype*() = t and + ma.getArgument(0) = sink.asExpr() + ) + } +} + +/** + * A call to `SSLParameters.setEndpointIdentificationAlgorithm` with a non-null and non-zero parameter. + */ +private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess { + SafeSetEndpointIdentificationAlgorithm() { + this.getMethod().hasName("setEndpointIdentificationAlgorithm") and + this.getMethod().getDeclaringType() instanceof SSLParameters and + not this.getArgument(0) instanceof NullLiteral and + not this.getArgument(0).(CompileTimeConstantExpr).getStringValue().length() = 0 + } +} diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql index 605e546d3d1..344faa7f86b 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql @@ -1,21 +1,7 @@ import java -import semmle.code.java.dataflow.FlowSources -import semmle.code.java.dataflow.TaintTracking -import semmle.code.java.security.UnsafeCertTrust +import semmle.code.java.security.UnsafeCertTrustQuery import TestUtilities.InlineExpectationsTest -class Conf extends TaintTracking::Configuration { - Conf() { this = "qltest:cwe:unsafe-cert-trust" } - - override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } - - override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } - - override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer instanceof SslUnsafeCertTrustSanitizer - } -} - class UnsafeCertTrustTest extends InlineExpectationsTest { UnsafeCertTrustTest() { this = "HasUnsafeCertTrustTest" } @@ -26,7 +12,9 @@ class UnsafeCertTrustTest extends InlineExpectationsTest { exists(Expr unsafeTrust | unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet or - exists(Conf config | config.hasFlowTo(DataFlow::exprNode(unsafeTrust))) + exists(SslEndpointIdentificationFlowConfig config | + config.hasFlowTo(DataFlow::exprNode(unsafeTrust)) + ) | unsafeTrust.getLocation() = location and element = unsafeTrust.toString() and From c16181dd2f9c944b4fe26908e2cffc1cb5ed49f9 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 21 Jul 2021 11:40:02 +0200 Subject: [PATCH 117/196] QLDocs --- java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll index 61f890a1d47..954af24dbbb 100644 --- a/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll +++ b/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll @@ -5,6 +5,9 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.UnsafeCertTrust import semmle.code.java.security.Encryption +/** + * A taint flow configuration for SSL connections created without a proper certificate trust configuration. + */ class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { SslEndpointIdentificationFlowConfig() { this = "SslEndpointIdentificationFlowConfig" } From 9ffc5ab1839decc10361f8d35e4fab9debe290dc Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 26 Jul 2021 16:58:45 +0200 Subject: [PATCH 118/196] Update java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll Co-authored-by: Marcono1234 --- java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll index 954af24dbbb..05bd9825a58 100644 --- a/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll +++ b/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll @@ -53,7 +53,7 @@ private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { } /** - * A call to `SSLParameters.setEndpointIdentificationAlgorithm` with a non-null and non-zero parameter. + * A call to `SSLParameters.setEndpointIdentificationAlgorithm` with a non-null and non-empty parameter. */ private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess { SafeSetEndpointIdentificationAlgorithm() { From 03020582afb8c59c352d5591db9cd14697c227ac Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 29 Jul 2021 17:16:09 +0200 Subject: [PATCH 119/196] Apply suggestions from code review Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com> --- .../Security/CWE/CWE-273/UnsafeCertTrust.qhelp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp index 6dc4f14e044..8545b3ffbb6 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp @@ -4,7 +4,7 @@ -

    Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (the later is checked by the java/insecure-hostname-verifier query). Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.

    +

    Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (the later is checked by the java/insecure-hostname-verifier query). The trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.

    When SSLSocket or SSLEngine are created without a secure setEndpointIdentificationAlgorithm, hostname verification is disabled by default.

    This query checks whether setEndpointIdentificationAlgorithm is missing, thereby making the application vulnerable to man-in-the-middle attacks. The query also covers insecure configurations of com.rabbitmq.client.ConnectionFactory.

    @@ -21,30 +21,30 @@
  • -Testing Endpoint Identify Verification (MSTG-NETWORK-3) +Testing Endpoint Identify Verification (MSTG-NETWORK-3).
  • - SSLParameters.setEndpointIdentificationAlgorithm documentation + SSLParameters.setEndpointIdentificationAlgorithm documentation.
  • RabbitMQ: - ConnectionFactory.enableHostnameVerification documentation + ConnectionFactory.enableHostnameVerification documentation.
  • RabbitMQ: - Using TLS in the Java Client + Using TLS in the Java Client.
  • -CVE-2018-17187: Apache Qpid Proton-J transport issue with hostname verification +CVE-2018-17187: Apache Qpid Proton-J transport issue with hostname verification.
  • -CVE-2018-8034: Apache Tomcat - host name verification when using TLS with the WebSocket client +CVE-2018-8034: Apache Tomcat - host name verification when using TLS with the WebSocket client.
  • -CVE-2018-11087: Pivotal Spring AMQP vulnerability due to lack of hostname validation +CVE-2018-11087: Pivotal Spring AMQP vulnerability due to lack of hostname validation.
  • -CVE-2018-11775: TLS hostname verification issue when using the Apache ActiveMQ Client +CVE-2018-11775: TLS hostname verification issue when using the Apache ActiveMQ Client.
  • From 101ad777e3430f0be2bc983d4564fffdf50b730d Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 12 Nov 2021 10:50:07 +0100 Subject: [PATCH 120/196] Move things around after rebase --- .../code/java/frameworks/Networking.qll | 2 + .../semmle/code/java/security/Encryption.qll | 4 +- .../java/security/UnsafeCertTrustQuery.qll | 0 .../semmle/code/java/security/Encryption.qll | 375 ------------------ 4 files changed, 5 insertions(+), 376 deletions(-) rename java/ql/{src => lib}/semmle/code/java/security/UnsafeCertTrustQuery.qll (100%) delete mode 100644 java/ql/src/semmle/code/java/security/Encryption.qll diff --git a/java/ql/lib/semmle/code/java/frameworks/Networking.qll b/java/ql/lib/semmle/code/java/frameworks/Networking.qll index c45b7036434..daa1f4ca8f9 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Networking.qll @@ -47,6 +47,7 @@ class SocketGetInputStreamMethod extends Method { } } +/** The method `java.net.Socket::getOutputStream`. */ class SocketGetOutputStreamMethod extends Method { SocketGetOutputStreamMethod() { this.getDeclaringType() instanceof TypeSocket and @@ -164,6 +165,7 @@ class CreateSocketMethod extends Method { } } +/** The method `javax.net.Socket::connect`. */ class SocketConnectMethod extends Method { SocketConnectMethod() { this.hasName("connect") and diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index 57c91d9cd55..513c4c0099c 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -34,10 +34,12 @@ class SSLSession extends RefType { SSLSession() { this.hasQualifiedName("javax.net.ssl", "SSLSession") } } +/** The `javax.net.ssl.SSLEngine` class. */ class SSLEngine extends RefType { SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } } +/** The `javax.net.ssl.SSLSocket` class. */ class SSLSocket extends RefType { SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } } @@ -221,7 +223,7 @@ string getInsecureAlgorithmRegex() { string getASecureAlgorithmName() { result = [ - "RSA", "SHA256", "SHA512", "CCM", "GCM", "AES([^a-zA-Z](?!ECB|CBC/PKCS[57]Padding)).*", + "RSA", "SHA256", "SHA512", "CCM", "GCM", "AES(?![^a-zA-Z](ECB|CBC/PKCS[57]Padding))", "Blowfish", "ECIES" ] } diff --git a/java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll similarity index 100% rename from java/ql/src/semmle/code/java/security/UnsafeCertTrustQuery.qll rename to java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll diff --git a/java/ql/src/semmle/code/java/security/Encryption.qll b/java/ql/src/semmle/code/java/security/Encryption.qll deleted file mode 100644 index e8fab54fc73..00000000000 --- a/java/ql/src/semmle/code/java/security/Encryption.qll +++ /dev/null @@ -1,375 +0,0 @@ -/** - * Provides predicates and classes relating to encryption in Java. - */ - -import java - -class SSLClass extends RefType { - SSLClass() { - exists(Class c | this.getASupertype*() = c | - c.hasQualifiedName("javax.net.ssl", _) or - c.hasQualifiedName("javax.rmi.ssl", _) - ) - } -} - -class X509TrustManager extends RefType { - X509TrustManager() { this.hasQualifiedName("javax.net.ssl", "X509TrustManager") } -} - -class HttpsURLConnection extends RefType { - HttpsURLConnection() { hasQualifiedName("javax.net.ssl", "HttpsURLConnection") } -} - -class SSLSocketFactory extends RefType { - SSLSocketFactory() { this.hasQualifiedName("javax.net.ssl", "SSLSocketFactory") } -} - -class SSLContext extends RefType { - SSLContext() { hasQualifiedName("javax.net.ssl", "SSLContext") } -} - -/** The `javax.net.ssl.SSLSession` class. */ -class SSLSession extends RefType { - SSLSession() { hasQualifiedName("javax.net.ssl", "SSLSession") } -} - -/** The `javax.net.ssl.SSLEngine` class. */ -class SSLEngine extends RefType { - SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } -} - -/** The `javax.net.ssl.SSLSocket` class. */ -class SSLSocket extends RefType { - SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } -} - -/** The `javax.net.ssl.SSLParameters` class. */ -class SSLParameters extends RefType { - SSLParameters() { this.hasQualifiedName("javax.net.ssl", "SSLParameters") } -} - -class HostnameVerifier extends RefType { - HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") } -} - -/** The Java class `javax.crypto.KeyGenerator`. */ -class KeyGenerator extends RefType { - KeyGenerator() { this.hasQualifiedName("javax.crypto", "KeyGenerator") } -} - -/** The Java class `java.security.KeyPairGenerator`. */ -class KeyPairGenerator extends RefType { - KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") } -} - -/** The `verify` method of the class `javax.net.ssl.HostnameVerifier`. */ -class HostnameVerifierVerify extends Method { - HostnameVerifierVerify() { - hasName("verify") and - getDeclaringType().getASupertype*() instanceof HostnameVerifier and - getParameterType(0) instanceof TypeString and - getParameterType(1) instanceof SSLSession - } -} - -class TrustManagerCheckMethod extends Method { - TrustManagerCheckMethod() { - (this.hasName("checkClientTrusted") or this.hasName("checkServerTrusted")) and - this.getDeclaringType().getASupertype*() instanceof X509TrustManager - } -} - -class CreateSocket extends Method { - CreateSocket() { - hasName("createSocket") and - getDeclaringType() instanceof SSLSocketFactory - } -} - -class GetSocketFactory extends Method { - GetSocketFactory() { - hasName("getSocketFactory") and - getDeclaringType() instanceof SSLContext - } -} - -/** The `createSSLEngine` method of the class `javax.net.ssl.SSLContext` */ -class CreateSslEngineMethod extends Method { - CreateSslEngineMethod() { - this.hasName("createSSLEngine") and - this.getDeclaringType() instanceof SSLContext - } -} - -class SetConnectionFactoryMethod extends Method { - SetConnectionFactoryMethod() { - hasName("setSSLSocketFactory") and - getDeclaringType().getASupertype*() instanceof HttpsURLConnection - } -} - -class SetHostnameVerifierMethod extends Method { - SetHostnameVerifierMethod() { - hasName("setHostnameVerifier") and - getDeclaringType().getASupertype*() instanceof HttpsURLConnection - } -} - -/** The `setDefaultHostnameVerifier` method of the class `javax.net.ssl.HttpsURLConnection`. */ -class SetDefaultHostnameVerifierMethod extends Method { - SetDefaultHostnameVerifierMethod() { - hasName("setDefaultHostnameVerifier") and - getDeclaringType().getASupertype*() instanceof HttpsURLConnection - } -} - -/** The `beginHandshake` method of the class `javax.net.ssl.SSLEngine`. */ -class BeginHandshakeMethod extends Method { - BeginHandshakeMethod() { - hasName("beginHandshake") and - getDeclaringType().getASupertype*() instanceof SSLEngine - } -} - -/** The `wrap` method of the class `javax.net.ssl.SSLEngine`. */ -class SslWrapMethod extends Method { - SslWrapMethod() { - hasName("wrap") and - getDeclaringType().getASupertype*() instanceof SSLEngine - } -} - -/** The `unwrap` method of the class `javax.net.ssl.SSLEngine`. */ -class SslUnwrapMethod extends Method { - SslUnwrapMethod() { - hasName("unwrap") and - getDeclaringType().getASupertype*() instanceof SSLEngine - } -} - -bindingset[algorithmString] -private string algorithmRegex(string algorithmString) { - // Algorithms usually appear in names surrounded by characters that are not - // alphabetical characters in the same case. This handles the upper and lower - // case cases. - result = - "((^|.*[^A-Z])(" + algorithmString + ")([^A-Z].*|$))" + - // or... - "|" + - // For lowercase, we want to be careful to avoid being confused by camelCase - // hence we require two preceding uppercase letters to be sure of a case switch, - // or a preceding non-alphabetic character - "((^|.*[A-Z]{2}|.*[^a-zA-Z])(" + algorithmString.toLowerCase() + ")([^a-z].*|$))" -} - -/** - * Gets the name of an algorithm that is known to be insecure. - */ -string getAnInsecureAlgorithmName() { - result = - [ - "DES", "RC2", "RC4", "RC5", - // ARCFOUR is a variant of RC4 - "ARCFOUR", - // Encryption mode ECB like AES/ECB/NoPadding is vulnerable to replay and other attacks - "ECB", - // CBC mode of operation with PKCS#5 or PKCS#7 padding is vulnerable to padding oracle attacks - "AES/CBC/PKCS[57]Padding" - ] -} - -/** - * Gets the name of a hash algorithm that is insecure if it is being used for - * encryption. - */ -string getAnInsecureHashAlgorithmName() { - result = "SHA1" or - result = "MD5" -} - -private string rankedInsecureAlgorithm(int i) { - // In this case we know these are being used for encryption, so we want to match - // weak hash algorithms too. - result = - rank[i](string s | s = getAnInsecureAlgorithmName() or s = getAnInsecureHashAlgorithmName()) -} - -private string insecureAlgorithmString(int i) { - i = 1 and result = rankedInsecureAlgorithm(i) - or - result = rankedInsecureAlgorithm(i) + "|" + insecureAlgorithmString(i - 1) -} - -/** - * Gets the regular expression used for matching strings that look like they - * contain an algorithm that is known to be insecure. - */ -string getInsecureAlgorithmRegex() { - result = algorithmRegex(insecureAlgorithmString(max(int i | exists(rankedInsecureAlgorithm(i))))) -} - -/** - * Gets the name of an algorithm that is known to be secure. - */ -string getASecureAlgorithmName() { - result = - [ - "RSA", "SHA256", "SHA512", "CCM", "GCM", "AES([^a-zA-Z](?!ECB|CBC/PKCS[57]Padding)).*", - "Blowfish", "ECIES" - ] -} - -private string rankedSecureAlgorithm(int i) { result = rank[i](getASecureAlgorithmName()) } - -private string secureAlgorithmString(int i) { - i = 1 and result = rankedSecureAlgorithm(i) - or - result = rankedSecureAlgorithm(i) + "|" + secureAlgorithmString(i - 1) -} - -/** - * Gets a regular expression for matching strings that look like they - * contain an algorithm that is known to be secure. - */ -string getSecureAlgorithmRegex() { - result = algorithmRegex(secureAlgorithmString(max(int i | exists(rankedSecureAlgorithm(i))))) -} - -/** - * DEPRECATED: Terminology has been updated. Use `getAnInsecureAlgorithmName()` - * instead. - */ -deprecated string algorithmBlacklist() { result = getAnInsecureAlgorithmName() } - -/** - * DEPRECATED: Terminology has been updated. Use - * `getAnInsecureHashAlgorithmName()` instead. - */ -deprecated string hashAlgorithmBlacklist() { result = getAnInsecureHashAlgorithmName() } - -/** - * DEPRECATED: Terminology has been updated. Use `getInsecureAlgorithmRegex()` instead. - */ -deprecated string algorithmBlacklistRegex() { result = getInsecureAlgorithmRegex() } - -/** - * DEPRECATED: Terminology has been updated. Use `getASecureAlgorithmName()` - * instead. - */ -deprecated string algorithmWhitelist() { result = getASecureAlgorithmName() } - -/** - * DEPRECATED: Terminology has been updated. Use `getSecureAlgorithmRegex()` instead. - */ -deprecated string algorithmWhitelistRegex() { result = getSecureAlgorithmRegex() } - -/** - * Any use of a cryptographic element that specifies an encryption - * algorithm. For example, methods returning ciphers, decryption methods, - * constructors of cipher classes, etc. - */ -abstract class CryptoAlgoSpec extends Top { - CryptoAlgoSpec() { this instanceof Call } - - abstract Expr getAlgoSpec(); -} - -abstract class JavaxCryptoAlgoSpec extends CryptoAlgoSpec { } - -class JavaxCryptoCipher extends JavaxCryptoAlgoSpec { - JavaxCryptoCipher() { - exists(Method m | m.getAReference() = this | - m.getDeclaringType().getQualifiedName() = "javax.crypto.Cipher" and - m.getName() = "getInstance" - ) - } - - override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } -} - -class JavaxCryptoSecretKey extends JavaxCryptoAlgoSpec { - JavaxCryptoSecretKey() { - exists(Constructor c | c.getAReference() = this | - c.getDeclaringType().getQualifiedName() = "javax.crypto.spec.SecretKeySpec" - ) - } - - override Expr getAlgoSpec() { - exists(ConstructorCall c | c = this | - if c.getNumArgument() = 2 then result = c.getArgument(1) else result = c.getArgument(3) - ) - } -} - -class JavaxCryptoKeyGenerator extends JavaxCryptoAlgoSpec { - JavaxCryptoKeyGenerator() { - exists(Method m | m.getAReference() = this | - m.getDeclaringType() instanceof KeyGenerator and - m.getName() = "getInstance" - ) - } - - override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } -} - -class JavaxCryptoKeyAgreement extends JavaxCryptoAlgoSpec { - JavaxCryptoKeyAgreement() { - exists(Method m | m.getAReference() = this | - m.getDeclaringType().getQualifiedName() = "javax.crypto.KeyAgreement" and - m.getName() = "getInstance" - ) - } - - override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } -} - -class JavaxCryptoKeyFactory extends JavaxCryptoAlgoSpec { - JavaxCryptoKeyFactory() { - exists(Method m | m.getAReference() = this | - m.getDeclaringType().getQualifiedName() = "javax.crypto.SecretKeyFactory" and - m.getName() = "getInstance" - ) - } - - override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } -} - -abstract class JavaSecurityAlgoSpec extends CryptoAlgoSpec { } - -class JavaSecurityMessageDigest extends JavaSecurityAlgoSpec { - JavaSecurityMessageDigest() { - exists(Constructor c | c.getAReference() = this | - c.getDeclaringType().hasQualifiedName("java.security", "MessageDigest") - ) - or - exists(Method m | m.getAReference() = this | - m.getDeclaringType().hasQualifiedName("java.security", "MessageDigest") and - m.getName() = "getInstance" - ) - } - - override Expr getAlgoSpec() { result = this.(Call).getArgument(0) } -} - -class JavaSecuritySignature extends JavaSecurityAlgoSpec { - JavaSecuritySignature() { - exists(Constructor c | c.getAReference() = this | - c.getDeclaringType().getQualifiedName() = "java.security.Signature" - ) - } - - override Expr getAlgoSpec() { result = this.(ConstructorCall).getArgument(0) } -} - -/** A method call to the Java class `java.security.KeyPairGenerator`. */ -class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec { - JavaSecurityKeyPairGenerator() { - exists(Method m | m.getAReference() = this | - m.getDeclaringType() instanceof KeyPairGenerator and - m.getName() = "getInstance" - ) - } - - override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) } -} From e442e50e6becbc970cd34fcc6a4d640ca29f222d Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 19 Jan 2022 16:41:31 +0100 Subject: [PATCH 121/196] Apply suggestions from code review Co-authored-by: Anders Schack-Mulligen --- java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll | 2 +- java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll index 05bd9825a58..767b86d4e41 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll @@ -60,6 +60,6 @@ private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess { this.getMethod().hasName("setEndpointIdentificationAlgorithm") and this.getMethod().getDeclaringType() instanceof SSLParameters and not this.getArgument(0) instanceof NullLiteral and - not this.getArgument(0).(CompileTimeConstantExpr).getStringValue().length() = 0 + not this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "" } } diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql index 12f20b40c93..13e1375d164 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -20,4 +20,4 @@ where exists(SslEndpointIdentificationFlowConfig config | config.hasFlowTo(DataFlow::exprNode(unsafeTrust)) ) -select unsafeTrust, "Unsafe configuration of trusted certificates" +select unsafeTrust, "Unsafe configuration of trusted certificates." From 695e77a21996fa77e8900093ad272506e9b6f911 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 19 Jan 2022 16:59:19 +0100 Subject: [PATCH 122/196] Simplify isSslSocket predicate --- java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll index 55c278a173c..c94864d8685 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -69,11 +69,7 @@ private class SslEngineServerMode extends SslUnsafeCertTrustSanitizer { * or the qualifier of `createSocket` is an instance of `SSLSocketFactory`. */ private predicate isSslSocket(MethodAccess createSocket) { - exists(Variable ssl, CastExpr ce | - ce.getExpr() = createSocket and - ce.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl and - ssl.getType() instanceof SSLSocket - ) + createSocket = any(CastExpr ce | ce.getType() instanceof SSLSocket).getExpr() or createSocket.getQualifier().getType().(RefType).getASupertype*() instanceof SSLSocketFactory } From e82ea7ad17a83cb24356badcdecf6b7f6c40f984 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 19 Jan 2022 17:21:46 +0100 Subject: [PATCH 123/196] Python: move regex injection configuration files I did not notice that these went to the wrong location in https://github.com/github/codeql/pull/6693. They should be in the dataflow folder with the rest of the data-flow configurations files, the injection folder is for old points-to based modeling. --- .../python/security/{injection => dataflow}/RegexInjection.qll | 0 .../{injection => dataflow}/RegexInjectionCustomizations.qll | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/lib/semmle/python/security/{injection => dataflow}/RegexInjection.qll (100%) rename python/ql/lib/semmle/python/security/{injection => dataflow}/RegexInjectionCustomizations.qll (100%) diff --git a/python/ql/lib/semmle/python/security/injection/RegexInjection.qll b/python/ql/lib/semmle/python/security/dataflow/RegexInjection.qll similarity index 100% rename from python/ql/lib/semmle/python/security/injection/RegexInjection.qll rename to python/ql/lib/semmle/python/security/dataflow/RegexInjection.qll diff --git a/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/RegexInjectionCustomizations.qll similarity index 100% rename from python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/RegexInjectionCustomizations.qll From aa10ad6a8a91ec72de4920a6e303e8c89325d2f2 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 19 Jan 2022 17:22:44 +0100 Subject: [PATCH 124/196] Python: Fix RegexInjection query, add old deprecated versions --- .../lib/semmle/python/security/injection/RegexInjection.qll | 6 ++++++ .../security/injection/RegexInjectionCustomizations.qll | 6 ++++++ python/ql/src/Security/CWE-730/RegexInjection.ql | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 python/ql/lib/semmle/python/security/injection/RegexInjection.qll create mode 100644 python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll diff --git a/python/ql/lib/semmle/python/security/injection/RegexInjection.qll b/python/ql/lib/semmle/python/security/injection/RegexInjection.qll new file mode 100644 index 00000000000..c0c0f42dbd6 --- /dev/null +++ b/python/ql/lib/semmle/python/security/injection/RegexInjection.qll @@ -0,0 +1,6 @@ +/** DEPRECATED: use semmle.python.security.dataflow.RegexInjection instead. */ + +private import semmle.python.security.dataflow.RegexInjection as New + +/** DEPRECATED: use semmle.python.security.dataflow.RegexInjection instead. */ +deprecated module RegexInjection = New::RegexInjection; diff --git a/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll new file mode 100644 index 00000000000..0738f2b58b6 --- /dev/null +++ b/python/ql/lib/semmle/python/security/injection/RegexInjectionCustomizations.qll @@ -0,0 +1,6 @@ +/** DEPRECATED: use semmle.python.security.dataflow.RegexInjectionCustomizations instead. */ + +private import semmle.python.security.dataflow.RegexInjectionCustomizations as New + +/** DEPRECATED: use semmle.python.security.dataflow.RegexInjectionCustomizations instead. */ +deprecated module RegexInjection = New::RegexInjection; diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql index 0dfb5b00d52..cc814a9b5d0 100644 --- a/python/ql/src/Security/CWE-730/RegexInjection.ql +++ b/python/ql/src/Security/CWE-730/RegexInjection.ql @@ -14,7 +14,7 @@ import python private import semmle.python.Concepts -import semmle.python.security.injection.RegexInjection +import semmle.python.security.dataflow.RegexInjection import DataFlow::PathGraph from From b9ee2960e2bd9a2b5e3a891a2ebe390f467e2607 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 19 Jan 2022 17:24:53 +0100 Subject: [PATCH 125/196] Python: Add change-note --- python/ql/lib/change-notes/2022-01-19-move-regex-injection.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 python/ql/lib/change-notes/2022-01-19-move-regex-injection.md diff --git a/python/ql/lib/change-notes/2022-01-19-move-regex-injection.md b/python/ql/lib/change-notes/2022-01-19-move-regex-injection.md new file mode 100644 index 00000000000..70f8a60a473 --- /dev/null +++ b/python/ql/lib/change-notes/2022-01-19-move-regex-injection.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* Moved the files defining regex injection configuration and customization, instead of `import semmle.python.security.injection.RegexInjection` please use `import semmle.python.security.dataflow.RegexInjection` (the same for `RegexInjectionCustomizations`). From 23548c50e1ae22b09959dcd850f3d99d8f6eab3f Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Wed, 19 Jan 2022 16:14:38 -0500 Subject: [PATCH 126/196] Fix typo in FileWritable --- java/ql/lib/semmle/code/java/security/FileWritable.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/security/FileWritable.qll b/java/ql/lib/semmle/code/java/security/FileWritable.qll index fbd359517e7..bd8329647da 100644 --- a/java/ql/lib/semmle/code/java/security/FileWritable.qll +++ b/java/ql/lib/semmle/code/java/security/FileWritable.qll @@ -62,7 +62,7 @@ private EnumConstant getAContainedEnumConstant(Expr enumSetRef) { private VarAccess getFileForPathConversion(Expr pathExpr) { pathExpr.getType().(RefType).hasQualifiedName("java.nio.file", "Path") and ( - // Look for conversion from `File` to `Path` using `file.getPath()`. + // Look for conversion from `File` to `Path` using `file.toPath()`. exists(MethodAccess fileToPath | fileToPath = pathExpr and result = fileToPath.getQualifier() and From 13a0ece25c43c85d32dcf5db664ea4fb5300dfb8 Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Thu, 20 Jan 2022 17:07:01 +1300 Subject: [PATCH 127/196] Ruby: Add test case: array constant barrier guard This guard isn't yet recognised as a `StringConstArrayInclusionCall`. --- .../dataflow/barrier-guards/barrier-guards.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.rb b/ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.rb index 2a26bbb3ae0..dc5b3802d59 100644 --- a/ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.rb +++ b/ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.rb @@ -31,3 +31,11 @@ else end foo + +FOO = ["foo"] + +if FOO.include?(foo) + foo +else + foo +end \ No newline at end of file From 6bae03a7cc56c74b4bf8d8feff4720a9ad3bc4de Mon Sep 17 00:00:00 2001 From: Harry Maclean Date: Thu, 20 Jan 2022 17:08:05 +1300 Subject: [PATCH 128/196] Ruby: Update string const barrier guard This change recognises guards like `FOO.include?`, where `FOO` is an array constant. --- ruby/ql/lib/codeql/ruby/dataflow/BarrierGuards.qll | 3 ++- .../dataflow/barrier-guards/barrier-guards.expected | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/BarrierGuards.qll b/ruby/ql/lib/codeql/ruby/dataflow/BarrierGuards.qll index 0c0ca749eac..fef6f62ac17 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/BarrierGuards.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/BarrierGuards.qll @@ -64,7 +64,8 @@ class StringConstArrayInclusionCall extends DataFlow::BarrierGuard, StringConstArrayInclusionCall() { exists(ArrayLiteral aLit | this.getExpr().getMethodName() = "include?" and - this.getExpr().getReceiver() = aLit + [this.getExpr().getReceiver(), this.getExpr().getReceiver().(ConstantReadAccess).getValue()] = + aLit | forall(Expr elem | elem = aLit.getAnElement() | elem instanceof StringLiteral) and this.getArgument(0) = checkedNode diff --git a/ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.expected b/ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.expected index e0940df3d03..4b7ef31d8a1 100644 --- a/ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.expected +++ b/ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.expected @@ -3,3 +3,4 @@ | barrier-guards.rb:15:4:15:15 | ... != ... | barrier-guards.rb:18:5:18:7 | foo | barrier-guards.rb:15:4:15:6 | foo | false | | barrier-guards.rb:21:8:21:19 | ... == ... | barrier-guards.rb:24:5:24:7 | foo | barrier-guards.rb:21:8:21:10 | foo | true | | barrier-guards.rb:27:8:27:19 | ... != ... | barrier-guards.rb:28:5:28:7 | foo | barrier-guards.rb:27:8:27:10 | foo | false | +| barrier-guards.rb:37:4:37:20 | call to include? | barrier-guards.rb:38:5:38:7 | foo | barrier-guards.rb:37:17:37:19 | foo | true | From 073d2f2c7501cc281e5a4a9de4cb150082d4a779 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 19 Jan 2022 09:26:51 +0100 Subject: [PATCH 129/196] C#: Add some example struct types, including one with a default constructor declarations. --- .../library-tests/csharp10/StructTypes.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 csharp/ql/test/library-tests/csharp10/StructTypes.cs diff --git a/csharp/ql/test/library-tests/csharp10/StructTypes.cs b/csharp/ql/test/library-tests/csharp10/StructTypes.cs new file mode 100644 index 00000000000..b337f773337 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/StructTypes.cs @@ -0,0 +1,19 @@ +using System; + +// Struct with user declared parameterless constructor. +public struct MyStructParameterlessConstructor +{ + public int X; + public readonly int Y; + public int Z { get; } + + public MyStructParameterlessConstructor() + { + X = 1; + Y = 2; + Z = 3; + } +} + +// Struct with compiler generated parameterless constructor. +public struct MyDefaultStruct { } \ No newline at end of file From 858aec38396e375d921409c36bde5f6647ad8969 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 19 Jan 2022 09:28:29 +0100 Subject: [PATCH 130/196] C#: Add test for source of the struct parameterless constructor(s). --- .../library-tests/csharp10/structTypes.expected | 5 +++++ .../ql/test/library-tests/csharp10/structTypes.ql | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 csharp/ql/test/library-tests/csharp10/structTypes.expected create mode 100644 csharp/ql/test/library-tests/csharp10/structTypes.ql diff --git a/csharp/ql/test/library-tests/csharp10/structTypes.expected b/csharp/ql/test/library-tests/csharp10/structTypes.expected new file mode 100644 index 00000000000..dc46b426ea5 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/structTypes.expected @@ -0,0 +1,5 @@ +structAllDefaultConstructors +| StructTypes.cs:4:15:4:46 | MyStructParameterlessConstructor | StructTypes.cs:10:12:10:43 | MyStructParameterlessConstructor | +| StructTypes.cs:19:15:19:29 | MyDefaultStruct | StructTypes.cs:19:15:19:29 | MyDefaultStruct | +structFromSourceDefaultConstructors +| StructTypes.cs:4:15:4:46 | MyStructParameterlessConstructor | StructTypes.cs:10:12:10:43 | MyStructParameterlessConstructor | diff --git a/csharp/ql/test/library-tests/csharp10/structTypes.ql b/csharp/ql/test/library-tests/csharp10/structTypes.ql new file mode 100644 index 00000000000..1b4f95f1305 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/structTypes.ql @@ -0,0 +1,15 @@ +import csharp + +predicate structDefaultConstructors(Struct struct, Constructor c) { + struct.getAConstructor() = c and + struct.getFile().getBaseName() = "StructTypes.cs" and + c.hasNoParameters() +} + +query predicate structAllDefaultConstructors(Struct struct, Constructor c) { + structDefaultConstructors(struct, c) +} + +query predicate structFromSourceDefaultConstructors(Struct struct, Constructor c) { + structDefaultConstructors(struct, c) and c.fromSource() +} From fc7f642734e1bebfd17fabc786d22ade922e7604 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 19 Jan 2022 10:34:20 +0100 Subject: [PATCH 131/196] C#: With expression examples for record structs, structs and anonymous types. --- .../library-tests/csharp10/RecordTypes.cs | 2 +- .../library-tests/csharp10/WithExpression.cs | 30 +++++++++++++++++++ .../csharp10/recordTypes.expected | 6 ++-- 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 csharp/ql/test/library-tests/csharp10/WithExpression.cs diff --git a/csharp/ql/test/library-tests/csharp10/RecordTypes.cs b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs index 92ad18085f0..994e4226927 100644 --- a/csharp/ql/test/library-tests/csharp10/RecordTypes.cs +++ b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs @@ -9,4 +9,4 @@ public record class MyClassRecord(DateTime stuff) { } public readonly record struct MyReadonlyRecordStruct(string Stuff) { } -public record struct MyRecordStruct(int Stuff) { } +public record struct MyRecordStruct1(int Stuff) { } diff --git a/csharp/ql/test/library-tests/csharp10/WithExpression.cs b/csharp/ql/test/library-tests/csharp10/WithExpression.cs new file mode 100644 index 00000000000..ba3b219cb91 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/WithExpression.cs @@ -0,0 +1,30 @@ +using System; + +public struct MyStruct +{ + public int X; + public MyStruct(int x) => X = x; +} + +public record struct MyRecordStruct2(int Y) { } + +public class MyWithExamples +{ + public void M1() + { + var s1 = new MyStruct(1); + var s2 = s1 with { X = 2 }; + } + + public void M2() + { + var r1 = new MyRecordStruct2(4); + var r2 = r1 with { Y = 6 }; + } + + public void M3() + { + var anon1 = new { A = 3, B = 4 }; + var anon2 = anon1 with { A = 5 }; + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp10/recordTypes.expected b/csharp/ql/test/library-tests/csharp10/recordTypes.expected index 75cef2ac7e7..786d42c8d71 100644 --- a/csharp/ql/test/library-tests/csharp10/recordTypes.expected +++ b/csharp/ql/test/library-tests/csharp10/recordTypes.expected @@ -2,10 +2,12 @@ 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 | +| RecordTypes.cs:12:1:12:51 | MyRecordStruct1 | +| WithExpression.cs:9:1:9:47 | MyRecordStruct2 | recordStructs | RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct | -| RecordTypes.cs:12:1:12:50 | MyRecordStruct | +| RecordTypes.cs:12:1:12:51 | MyRecordStruct1 | +| WithExpression.cs:9:1:9:47 | MyRecordStruct2 | recordClass | RecordTypes.cs:3:1:6:2 | MyEntry | | RecordTypes.cs:8:1:8:53 | MyClassRecord | From 210bad6c29a4326672f98170f05098e833bdfedc Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 19 Jan 2022 10:35:20 +0100 Subject: [PATCH 132/196] C#: Add test case for with expressions for record structs, structs and anonymous types. --- .../ql/test/library-tests/csharp10/withExpression.expected | 3 +++ csharp/ql/test/library-tests/csharp10/withExpression.ql | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 csharp/ql/test/library-tests/csharp10/withExpression.expected create mode 100644 csharp/ql/test/library-tests/csharp10/withExpression.ql diff --git a/csharp/ql/test/library-tests/csharp10/withExpression.expected b/csharp/ql/test/library-tests/csharp10/withExpression.expected new file mode 100644 index 00000000000..b9a3ede0a69 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/withExpression.expected @@ -0,0 +1,3 @@ +| WithExpression.cs:16:18:16:34 | ... with { ... } | MyStruct | WithExpression.cs:16:18:16:19 | access to local variable s1 | WithExpression.cs:16:26:16:34 | { ..., ... } | +| WithExpression.cs:22:18:22:34 | ... with { ... } | MyRecordStruct2 | WithExpression.cs:22:18:22:19 | access to local variable r1 | WithExpression.cs:22:26:22:34 | { ..., ... } | +| WithExpression.cs:28:21:28:40 | ... with { ... } | <>__AnonType0 | WithExpression.cs:28:21:28:25 | access to local variable anon1 | WithExpression.cs:28:32:28:40 | { ..., ... } | diff --git a/csharp/ql/test/library-tests/csharp10/withExpression.ql b/csharp/ql/test/library-tests/csharp10/withExpression.ql new file mode 100644 index 00000000000..52475e7a005 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/withExpression.ql @@ -0,0 +1,7 @@ +import csharp + +query predicate withExpressions(WithExpr with, string type, Expr expr, ObjectInitializer init) { + type = with.getType().toStringWithTypes() and + expr = with.getExpr() and + init = with.getInitializer() +} From 7d7ab5810892ed1dbeb91e7bdb5ece0cc5e0ed61 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 19 Jan 2022 12:29:41 +0100 Subject: [PATCH 133/196] C#: Add flow test for record struct fields. --- .../dataflow/fields/FieldFlow.expected | 33 +++++++++++++++++++ .../test/library-tests/dataflow/fields/J.cs | 12 +++++++ 2 files changed, 45 insertions(+) diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index 42791f4cb73..5d30fcb2346 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -802,10 +802,24 @@ edges | 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:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:44:14:44:15 | access to local variable r3 [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 | +| J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | J.cs:40:14:40:21 | access to property Prop1 | +| J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | J.cs:40:14:40:21 | access to property Prop1 | +| J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:43:36:43:52 | call to method Source : Object | J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | +| J.cs:43:36:43:52 | call to method Source : Object | J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | +| J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | J.cs:44:14:44:21 | access to property Prop1 | +| J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | J.cs:44:14:44:21 | access to property Prop1 | +| J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | J.cs:45:14:45:21 | access to property Prop2 | +| J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | J.cs:45:14:45:21 | access to property Prop2 | 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 | @@ -1681,6 +1695,22 @@ nodes | 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 | +| J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:40:14:40:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:40:14:40:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:43:36:43:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:43:36:43:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:44:14:44:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:44:14:44:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:45:14:45:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:45:14:45:21 | access to property Prop2 | semmle.label | access to property Prop2 | 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 | @@ -1838,3 +1868,6 @@ subpaths | 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 | +| J.cs:40:14:40:21 | access to property Prop1 | J.cs:34:17:34:33 | call to method Source : Object | J.cs:40:14:40:21 | access to property Prop1 | $@ | J.cs:34:17:34:33 | call to method Source : Object | call to method Source : Object | +| J.cs:44:14:44:21 | access to property Prop1 | J.cs:34:17:34:33 | call to method Source : Object | J.cs:44:14:44:21 | access to property Prop1 | $@ | J.cs:34:17:34:33 | call to method Source : Object | call to method Source : Object | +| J.cs:45:14:45:21 | access to property Prop2 | J.cs:43:36:43:52 | call to method Source : Object | J.cs:45:14:45:21 | access to property Prop2 | $@ | J.cs:43:36:43:52 | 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 4353d646b49..71b793646ca 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/J.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs @@ -35,6 +35,18 @@ public class J var r1 = new RecordStruct(o, null); Sink(r1.Prop1); // $ hasValueFlow=2 Sink(r1.Prop2); // no flow + + var r2 = r1 with { }; + Sink(r2.Prop1); // $ hasValueFlow=2 + Sink(r2.Prop2); // no flow + + var r3 = r1 with { Prop2 = Source(3) }; + Sink(r3.Prop1); // $ hasValueFlow=2 + Sink(r3.Prop2); // $ hasValueFlow=3 + + var r4 = r1 with { Prop1 = null }; + Sink(r4.Prop1); // no flow + Sink(r4.Prop2); // no flow } public static void Sink(object o) { } From 7cd05fb6853bd4cd71cd756978fe1a63c423d554 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 12 Nov 2021 12:05:16 +0100 Subject: [PATCH 134/196] Move from experimental --- .../Security/CWE/CWE-295/InsecureTrustManager.java | 0 .../Security/CWE/CWE-295/InsecureTrustManager.qhelp | 0 .../Security/CWE/CWE-295/InsecureTrustManager.ql | 0 .../CWE-295/InsecureTrustManager/InsecureTrustManager.qlref | 1 - .../CWE-295/InsecureTrustManager/InsecureTrustManager.expected | 0 .../CWE-295/InsecureTrustManager/InsecureTrustManager.qlref | 1 + .../CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename java/ql/src/{experimental => }/Security/CWE/CWE-295/InsecureTrustManager.java (100%) rename java/ql/src/{experimental => }/Security/CWE/CWE-295/InsecureTrustManager.qhelp (100%) rename java/ql/src/{experimental => }/Security/CWE/CWE-295/InsecureTrustManager.ql (100%) delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref rename java/ql/test/{experimental => }/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected (100%) create mode 100644 java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref rename java/ql/test/{experimental => }/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java (100%) diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.java b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.java rename to java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.qhelp b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.qhelp rename to java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.ql b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.ql rename to java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref b/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref deleted file mode 100644 index 9950f627659..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-295/InsecureTrustManager.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected rename to java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref new file mode 100644 index 00000000000..9bb2ecf04e8 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-295/InsecureTrustManager.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java rename to java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java From ab4dc30f5457b9de8b3daf6adc77e655c306dacb Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 12 Nov 2021 14:51:56 +0100 Subject: [PATCH 135/196] Refactor into libraries --- .../java/security/InsecureTrustManager.qll | 101 +++++++++++++++++ .../security/InsecureTrustManagerQuery.qll | 20 ++++ .../CWE/CWE-295/InsecureTrustManager.ql | 107 +----------------- .../InsecureTrustManager.expected | 45 +++----- 4 files changed, 141 insertions(+), 132 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll create mode 100644 java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll diff --git a/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll b/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll new file mode 100644 index 00000000000..f8b4dca8a4e --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll @@ -0,0 +1,101 @@ +import java +private import semmle.code.java.controlflow.Guards +private import semmle.code.java.security.Encryption +private import semmle.code.java.security.SecurityFlag + +/** The creation of an insecure `TrustManager`. */ +abstract class InsecureTrustManagerSource extends DataFlow::Node { } + +private class DefaultInsecureTrustManagerSource extends InsecureTrustManagerSource { + DefaultInsecureTrustManagerSource() { + this.asExpr().(ClassInstanceExpr).getConstructedType() instanceof InsecureX509TrustManager + } +} + +/** + * The use of a `TrustManager` in an SSL context. + * Intentionally insecure connections are not considered sinks. + */ +abstract class InsecureTrustManagerSink extends DataFlow::Node { + InsecureTrustManagerSink() { not isGuardedByInsecureFlag(this) } +} + +private class DefaultInsecureTrustManagerSink extends InsecureTrustManagerSink { + DefaultInsecureTrustManagerSink() { + exists(MethodAccess ma, Method m | + m.hasName("init") and + m.getDeclaringType() instanceof SSLContext and + ma.getMethod() = m + | + ma.getArgument(1) = this.asExpr() + ) + } +} + +/** Holds if `node` is guarded by a flag that suggests an intentionally insecure use. */ +private predicate isGuardedByInsecureFlag(DataFlow::Node node) { + exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | + g = getASecurityFeatureFlagGuard() or g = getAnInsecureTrustManagerFlagGuard() + ) +} + +/** + * An insecure `X509TrustManager`. + * An `X509TrustManager` is considered insecure if it never throws a `CertificateException` + * and therefore implicitly trusts any certificate as valid. + */ +private class InsecureX509TrustManager extends RefType { + InsecureX509TrustManager() { + this.getASupertype*() instanceof X509TrustManager and + exists(Method m | + m.getDeclaringType() = this and + m.hasName("checkServerTrusted") and + not mayThrowCertificateException(m) + ) + } +} + +/** The `java.security.cert.CertificateException` class. */ +private class CertificateException extends RefType { + CertificateException() { this.hasQualifiedName("java.security.cert", "CertificateException") } +} + +/** + * Holds if: + * - `m` may `throw` a `CertificateException`, or + * - `m` calls another method that may throw, or + * - `m` calls a method declared to throw a `CertificateException`, but for which no source is available + */ +private predicate mayThrowCertificateException(Method m) { + exists(ThrowStmt throwStmt | + throwStmt.getThrownExceptionType().getASupertype*() instanceof CertificateException + | + throwStmt.getEnclosingCallable() = m + ) + or + exists(Method otherMethod | m.polyCalls(otherMethod) | + mayThrowCertificateException(otherMethod) + or + not otherMethod.fromSource() and + otherMethod.getAnException().getType().getASupertype*() instanceof CertificateException + ) +} + +/** + * Flags suggesting a deliberately insecure `TrustManager` usage. + */ +private class InsecureTrustManagerFlag extends FlagKind { + InsecureTrustManagerFlag() { this = "InsecureTrustManagerFlag" } + + bindingset[result] + override string getAFlagName() { + result + .regexpMatch("(?i).*(secure|disable|selfCert|selfSign|validat|verif|trust|ignore|nocertificatecheck).*") and + result != "equalsIgnoreCase" + } +} + +/** Gets a guard that represents a (likely) flag controlling an insecure `TrustManager` use. */ +private Guard getAnInsecureTrustManagerFlagGuard() { + result = any(InsecureTrustManagerFlag flag).getAFlag().asExpr() +} diff --git a/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll new file mode 100644 index 00000000000..7d9bee65e50 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll @@ -0,0 +1,20 @@ +/** Provides taint tracking configurations to be used in Trust Manager queries. */ + +import java +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.security.Encryption +import semmle.code.java.security.InsecureTrustManager + +/** + * A configuration to model the flow of an insecure `TrustManager` + * to the initialization of an SSL context. + */ +class InsecureTrustManagerConfiguration extends TaintTracking::Configuration { + InsecureTrustManagerConfiguration() { this = "InsecureTrustManagerConfiguration" } + + override predicate isSource(DataFlow::Node source) { + source instanceof InsecureTrustManagerSource + } + + override predicate isSink(DataFlow::Node sink) { sink instanceof InsecureTrustManagerSink } +} diff --git a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql index 598113ed5cd..46859592849 100644 --- a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql +++ b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql @@ -10,108 +10,11 @@ */ import java -import semmle.code.java.controlflow.Guards import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.FlowSources -import semmle.code.java.security.Encryption -import semmle.code.java.security.SecurityFlag +import semmle.code.java.security.InsecureTrustManagerQuery import DataFlow::PathGraph -/** - * An insecure `X509TrustManager`. - * An `X509TrustManager` is considered insecure if it never throws a `CertificateException` - * and therefore implicitly trusts any certificate as valid. - */ -class InsecureX509TrustManager extends RefType { - InsecureX509TrustManager() { - this.getASupertype*() instanceof X509TrustManager and - exists(Method m | - m.getDeclaringType() = this and - m.hasName("checkServerTrusted") and - not mayThrowCertificateException(m) - ) - } -} - -/** The `java.security.cert.CertificateException` class. */ -private class CertificateException extends RefType { - CertificateException() { this.hasQualifiedName("java.security.cert", "CertificateException") } -} - -/** - * Holds if: - * - `m` may `throw` a `CertificateException`, or - * - `m` calls another method that may throw, or - * - `m` calls a method declared to throw a `CertificateException`, but for which no source is available - */ -private predicate mayThrowCertificateException(Method m) { - exists(ThrowStmt throwStmt | - throwStmt.getThrownExceptionType().getASupertype*() instanceof CertificateException - | - throwStmt.getEnclosingCallable() = m - ) - or - exists(Method otherMethod | m.polyCalls(otherMethod) | - mayThrowCertificateException(otherMethod) - or - not otherMethod.fromSource() and - otherMethod.getAnException().getType().getASupertype*() instanceof CertificateException - ) -} - -/** - * A configuration to model the flow of an `InsecureX509TrustManager` to an `SSLContext.init` call. - */ -class InsecureTrustManagerConfiguration extends TaintTracking::Configuration { - InsecureTrustManagerConfiguration() { this = "InsecureTrustManagerConfiguration" } - - override predicate isSource(DataFlow::Node source) { - source.asExpr().(ClassInstanceExpr).getConstructedType() instanceof InsecureX509TrustManager - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodAccess ma, Method m | - m.hasName("init") and - m.getDeclaringType() instanceof SSLContext and - ma.getMethod() = m - | - ma.getArgument(1) = sink.asExpr() - ) - } -} - -/** - * Flags suggesting a deliberately insecure `TrustManager` usage. - */ -private class InsecureTrustManagerFlag extends FlagKind { - InsecureTrustManagerFlag() { this = "InsecureTrustManagerFlag" } - - bindingset[result] - override string getAFlagName() { - result - .regexpMatch("(?i).*(secure|disable|selfCert|selfSign|validat|verif|trust|ignore|nocertificatecheck).*") and - result != "equalsIgnoreCase" - } -} - -/** Gets a guard that represents a (likely) flag controlling an insecure `TrustManager` use. */ -private Guard getAnInsecureTrustManagerFlagGuard() { - result = any(InsecureTrustManagerFlag flag).getAFlag().asExpr() -} - -/** Holds if `node` is guarded by a flag that suggests an intentionally insecure use. */ -private predicate isNodeGuardedByFlag(DataFlow::Node node) { - exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | - g = getASecurityFeatureFlagGuard() or g = getAnInsecureTrustManagerFlagGuard() - ) -} - -from - DataFlow::PathNode source, DataFlow::PathNode sink, InsecureTrustManagerConfiguration cfg, - RefType trustManager -where - cfg.hasFlowPath(source, sink) and - not isNodeGuardedByFlag(sink.getNode()) and - trustManager = source.getNode().asExpr().(ClassInstanceExpr).getConstructedType() -select sink, source, sink, "$@ that is defined $@ and trusts any certificate, is used here.", - source, "This trustmanager", trustManager, "here" +from DataFlow::PathNode source, DataFlow::PathNode sink +where any(InsecureTrustManagerConfiguration cfg).hasFlowPath(source, sink) +select sink, source, sink, "This $@, that is defined $@, trusts any certificate and is used here.", + source, "TrustManager", source.getNode().asExpr().(ClassInstanceExpr).getConstructedType(), "here" diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected index 964c65889d4..993547bdf82 100644 --- a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected @@ -1,16 +1,10 @@ edges | InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:122:22:122:33 | trustManager | | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:130:34:130:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:131:23:131:34 | trustManager | -| InsecureTrustManagerTest.java:130:55:130:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:130:34:130:82 | {...} [[]] : InsecureTrustManager | | InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:152:23:152:34 | trustManager | | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:172:34:172:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:173:23:173:34 | trustManager | -| InsecureTrustManagerTest.java:172:55:172:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:172:34:172:82 | {...} [[]] : InsecureTrustManager | | InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:194:23:194:34 | trustManager | | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:214:34:214:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:215:23:215:34 | trustManager | -| InsecureTrustManagerTest.java:214:55:214:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:214:34:214:82 | {...} [[]] : InsecureTrustManager | | InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:236:23:236:34 | trustManager | | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | | InsecureTrustManagerTest.java:257:34:257:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:258:23:258:34 | trustManager | @@ -39,21 +33,12 @@ nodes | InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | | InsecureTrustManagerTest.java:122:22:122:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:130:34:130:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:130:55:130:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:131:23:131:34 | trustManager | semmle.label | trustManager | | InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | | InsecureTrustManagerTest.java:152:23:152:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:172:34:172:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:172:55:172:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:173:23:173:34 | trustManager | semmle.label | trustManager | | InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | | InsecureTrustManagerTest.java:194:23:194:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:214:34:214:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:214:55:214:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:215:23:215:34 | trustManager | semmle.label | trustManager | | InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | | InsecureTrustManagerTest.java:236:23:236:34 | trustManager | semmle.label | trustManager | @@ -92,18 +77,18 @@ nodes | InsecureTrustManagerTest.java:415:22:415:33 | trustManager | semmle.label | trustManager | subpaths #select -| InsecureTrustManagerTest.java:122:22:122:33 | trustManager | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:122:22:122:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:152:23:152:34 | trustManager | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:152:23:152:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:194:23:194:34 | trustManager | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:194:23:194:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:236:23:236:34 | trustManager | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:236:23:236:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:258:23:258:34 | trustManager | InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:258:23:258:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:281:23:281:34 | trustManager | InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:281:23:281:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:306:22:306:33 | trustManager | InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:306:22:306:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:320:22:320:33 | trustManager | InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:320:22:320:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:334:22:334:33 | trustManager | InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:334:22:334:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:348:22:348:33 | trustManager | InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:348:22:348:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:362:22:362:33 | trustManager | InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:362:22:362:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:376:22:376:33 | trustManager | InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:376:22:376:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:391:22:391:33 | trustManager | InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:391:22:391:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:406:22:406:33 | trustManager | InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:406:22:406:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:415:22:415:33 | trustManager | InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:415:22:415:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:122:22:122:33 | trustManager | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:122:22:122:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:152:23:152:34 | trustManager | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:152:23:152:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:194:23:194:34 | trustManager | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:194:23:194:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:236:23:236:34 | trustManager | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:236:23:236:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:258:23:258:34 | trustManager | InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:258:23:258:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:281:23:281:34 | trustManager | InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:281:23:281:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:306:22:306:33 | trustManager | InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:306:22:306:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:320:22:320:33 | trustManager | InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:320:22:320:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:334:22:334:33 | trustManager | InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:334:22:334:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:348:22:348:33 | trustManager | InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:348:22:348:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:362:22:362:33 | trustManager | InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:362:22:362:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:376:22:376:33 | trustManager | InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:376:22:376:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:391:22:391:33 | trustManager | InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:391:22:391:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:406:22:406:33 | trustManager | InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:406:22:406:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | +| InsecureTrustManagerTest.java:415:22:415:33 | trustManager | InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:415:22:415:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | From d58bb4753e4ec834d7fdb7444596b1474916eb92 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 12 Nov 2021 15:03:24 +0100 Subject: [PATCH 136/196] Refactor tests --- .../CWE/CWE-295/InsecureTrustManager.ql | 2 +- .../InsecureTrustManager.expected | 94 --------- .../InsecureTrustManager.qlref | 1 - .../InsecureTrustManagerTest.expected | 0 .../InsecureTrustManagerTest.java | 186 ++++++------------ .../InsecureTrustManagerTest.ql | 11 ++ 6 files changed, 76 insertions(+), 218 deletions(-) delete mode 100644 java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected delete mode 100644 java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref create mode 100644 java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.expected create mode 100644 java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql diff --git a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql index 46859592849..3f7f6e3b705 100644 --- a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql +++ b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql @@ -16,5 +16,5 @@ import DataFlow::PathGraph from DataFlow::PathNode source, DataFlow::PathNode sink where any(InsecureTrustManagerConfiguration cfg).hasFlowPath(source, sink) -select sink, source, sink, "This $@, that is defined $@, trusts any certificate and is used here.", +select sink, source, sink, "This $@, which is defined $@ and trusts any certificate, is used here.", source, "TrustManager", source.getNode().asExpr().(ClassInstanceExpr).getConstructedType(), "here" diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected deleted file mode 100644 index 993547bdf82..00000000000 --- a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected +++ /dev/null @@ -1,94 +0,0 @@ -edges -| InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:122:22:122:33 | trustManager | -| InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:152:23:152:34 | trustManager | -| InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:194:23:194:34 | trustManager | -| InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:236:23:236:34 | trustManager | -| InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:257:34:257:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:258:23:258:34 | trustManager | -| InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:257:34:257:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:280:34:280:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:281:23:281:34 | trustManager | -| InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:280:34:280:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:305:33:305:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:306:22:306:33 | trustManager | -| InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:305:33:305:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:319:33:319:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:320:22:320:33 | trustManager | -| InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:319:33:319:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:333:33:333:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:334:22:334:33 | trustManager | -| InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:333:33:333:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:347:33:347:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:348:22:348:33 | trustManager | -| InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:347:33:347:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:361:33:361:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:362:22:362:33 | trustManager | -| InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:361:33:361:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:375:33:375:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:376:22:376:33 | trustManager | -| InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:375:33:375:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:390:33:390:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:391:22:391:33 | trustManager | -| InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:390:33:390:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:405:33:405:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:406:22:406:33 | trustManager | -| InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:405:33:405:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:414:33:414:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:415:22:415:33 | trustManager | -| InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:414:33:414:81 | {...} [[]] : InsecureTrustManager | -nodes -| InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:122:22:122:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:152:23:152:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:194:23:194:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:236:23:236:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:257:34:257:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:258:23:258:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:280:34:280:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:281:23:281:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:305:33:305:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:306:22:306:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:319:33:319:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:320:22:320:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:333:33:333:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:334:22:334:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:347:33:347:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:348:22:348:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:361:33:361:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:362:22:362:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:375:33:375:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:376:22:376:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:390:33:390:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:391:22:391:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:405:33:405:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:406:22:406:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:414:33:414:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:415:22:415:33 | trustManager | semmle.label | trustManager | -subpaths -#select -| InsecureTrustManagerTest.java:122:22:122:33 | trustManager | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:122:22:122:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:152:23:152:34 | trustManager | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:152:23:152:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:194:23:194:34 | trustManager | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:194:23:194:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:236:23:236:34 | trustManager | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:236:23:236:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:258:23:258:34 | trustManager | InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:258:23:258:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:281:23:281:34 | trustManager | InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:281:23:281:34 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:306:22:306:33 | trustManager | InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:306:22:306:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:320:22:320:33 | trustManager | InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:320:22:320:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:334:22:334:33 | trustManager | InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:334:22:334:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:348:22:348:33 | trustManager | InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:348:22:348:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:362:22:362:33 | trustManager | InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:362:22:362:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:376:22:376:33 | trustManager | InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:376:22:376:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:391:22:391:33 | trustManager | InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:391:22:391:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:406:22:406:33 | trustManager | InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:406:22:406:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:415:22:415:33 | trustManager | InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:415:22:415:33 | trustManager | This $@, that is defined $@, trusts any certificate and is used here. | InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | TrustManager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref deleted file mode 100644 index 9bb2ecf04e8..00000000000 --- a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref +++ /dev/null @@ -1 +0,0 @@ -Security/CWE/CWE-295/InsecureTrustManager.ql diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.expected b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java index 5b314d464d4..ba15609c655 100644 --- a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java @@ -39,14 +39,12 @@ public class InsecureTrustManagerTest { } @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { - // BAD: Does not verify the certificate chain, allowing any certificate. - } + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException {} @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { - - } + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException {} } public static void main(String[] args) throws Exception { @@ -88,8 +86,9 @@ public class InsecureTrustManagerTest { } - private static void directSecureTrustManagerCall() throws NoSuchAlgorithmException, KeyStoreException, IOException, - CertificateException, FileNotFoundException, KeyManagementException, MalformedURLException { + private static void directSecureTrustManagerCall() + throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, + FileNotFoundException, KeyManagementException, MalformedURLException { SSLContext context = SSLContext.getInstance("TLS"); File certificateFile = new File("path/to/self-signed-certificate"); // Create a `KeyStore` with default type @@ -98,49 +97,46 @@ public class InsecureTrustManagerTest { keyStore.load(null, null); X509Certificate generatedCertificate; try (InputStream cert = new FileInputStream(certificateFile)) { - generatedCertificate = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(cert); + generatedCertificate = (X509Certificate) CertificateFactory.getInstance("X509") + .generateCertificate(cert); } // Add the self-signed certificate to the key store keyStore.setCertificateEntry(certificateFile.getName(), generatedCertificate); // Get default `TrustManagerFactory` - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // Use it with our modified key store that trusts our self-signed certificate tmf.init(keyStore); TrustManager[] trustManagers = tmf.getTrustManagers(); - context.init(null, trustManagers, null); // GOOD, we are not using a custom `TrustManager` but instead have - // added the self-signed certificate we want to trust to the key - // store. Note, the `trustManagers` will **only** trust this one - // certificate. + // we are not using a custom `TrustManager` but instead have added the self-signed + // certificate we want to trust to the key store. Note, the `trustManagers` will **only** + // trust this one certificate. + context.init(null, trustManagers, null); // Safe URL url = new URL("https://self-signed.badssl.com/"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(context.getSocketFactory()); } - private static void directInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { + private static void directInsecureTrustManagerCall() + throws NoSuchAlgorithmException, KeyManagementException { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } private static void namedVariableFlagDirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (TRUST_ALL) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // GOOD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // Safe: guarded by feature flag } } private static void namedVariableFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (TRUST_ALL) { - disableTrustManager(); // GOOD [But the disableTrustManager method itself is still detected]: Calls a - // method that install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + disableTrustManager(); // Safe: guarded by feature flag } } @@ -148,20 +144,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (SOME_NAME_THAT_IS_NOT_A_FLAG_NAME) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } } private static void noNamedVariableFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (SOME_NAME_THAT_IS_NOT_A_FLAG_NAME) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -169,20 +160,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (Boolean.parseBoolean(System.getProperty("TRUST_ALL"))) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // GOOD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // Safe: guarded by feature flag } } private static void stringLiteralFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (Boolean.parseBoolean(System.getProperty("TRUST_ALL"))) { - disableTrustManager(); // GOOD [But the disableTrustManager method itself is still detected]: Calls a - // method that install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + disableTrustManager(); // Safe: guarded by feature flag } } @@ -190,20 +176,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (Boolean.parseBoolean(System.getProperty("SOME_NAME_THAT_IS_NOT_A_FLAG_NAME"))) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } } private static void noStringLiteralFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (Boolean.parseBoolean(System.getProperty("SOME_NAME_THAT_IS_NOT_A_FLAG_NAME"))) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -211,20 +192,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (isDisableTrust()) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // GOOD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // Safe: guarded by feature flag } } private static void methodAccessFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (isDisableTrust()) { - disableTrustManager(); // GOOD [But the disableTrustManager method itself is still detected]: Calls a - // method that install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + disableTrustManager(); // Safe: guarded by feature flag } } @@ -232,20 +208,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (is42TheAnswerForEverything()) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } } private static void noMethodAccessFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (is42TheAnswerForEverything()) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -254,10 +225,8 @@ public class InsecureTrustManagerTest { String schemaFromHttpRequest = "HTTPS"; if (schemaFromHttpRequest.equalsIgnoreCase("https")) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } } @@ -265,10 +234,7 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { String schemaFromHttpRequest = "HTTPS"; if (schemaFromHttpRequest.equalsIgnoreCase("https")) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -277,10 +243,8 @@ public class InsecureTrustManagerTest { String schemaFromHttpRequest = "HTTPS"; if (!schemaFromHttpRequest.equalsIgnoreCase("https")) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } } @@ -288,10 +252,7 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { String schemaFromHttpRequest = "HTTPS"; if (!schemaFromHttpRequest.equalsIgnoreCase("https")) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -302,10 +263,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } @@ -316,10 +275,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } @@ -330,10 +287,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } @@ -344,10 +299,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } @@ -358,10 +311,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } @@ -372,11 +323,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. - + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } private static void isEqualsIgnoreCaseNOTGuardingDirectInsecureTrustManagerCall() @@ -387,10 +335,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } @@ -402,19 +348,15 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } - private static void disableTrustManager() throws NoSuchAlgorithmException, KeyManagementException { + private static void disableTrustManager() + throws NoSuchAlgorithmException, KeyManagementException { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the - // certificate - // chain, allowing any certificate. The method name suggests that this may be - // intentional, but we flag it anyway. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasTaintFlow } -} \ No newline at end of file +} diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql new file mode 100644 index 00000000000..3f83c2ee78c --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql @@ -0,0 +1,11 @@ +import java +import semmle.code.java.security.InsecureTrustManagerQuery +import TestUtilities.InlineFlowTest + +class InsecureTrustManagerTest extends InlineFlowTest { + override DataFlow::Configuration getValueFlowConfig() { none() } + + override TaintTracking::Configuration getTaintFlowConfig() { + result = any(InsecureTrustManagerConfiguration c) + } +} From 76a0853f5b8a8b2747cb97b59a140a8bac3591f8 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 19 Jan 2022 12:44:37 +0100 Subject: [PATCH 137/196] C#: Add struct declaration and update line numbers for the existing test cases. --- .../dataflow/fields/FieldFlow.expected | 322 ++++++++++++------ .../test/library-tests/dataflow/fields/J.cs | 43 +++ 2 files changed, 261 insertions(+), 104 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index 5d30fcb2346..836f3dfdf7f 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -776,50 +776,98 @@ 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: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:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | -| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | -| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | -| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:44:14:44:15 | access to local variable r3 [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 | -| J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | J.cs:40:14:40:21 | access to property Prop1 | -| J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | J.cs:40:14:40:21 | access to property Prop1 | -| J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | -| J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | -| J.cs:43:36:43:52 | call to method Source : Object | J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | -| J.cs:43:36:43:52 | call to method Source : Object | J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | -| J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | J.cs:44:14:44:21 | access to property Prop1 | -| J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | J.cs:44:14:44:21 | access to property Prop1 | -| J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | J.cs:45:14:45:21 | access to property Prop2 | -| J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | J.cs:45:14:45:21 | access to property Prop2 | +| J.cs:14:26:14:30 | field : Object | J.cs:14:66:14:70 | access to parameter field : Object | +| J.cs:14:26:14:30 | field : Object | J.cs:14:66:14:70 | access to parameter field : Object | +| J.cs:14:40:14:43 | prop : Object | J.cs:14:73:14:76 | access to parameter prop : Object | +| J.cs:14:40:14:43 | prop : Object | J.cs:14:73:14:76 | access to parameter prop : Object | +| J.cs:14:66:14:70 | access to parameter field : Object | J.cs:14:50:14:54 | [post] this access [field Field] : Object | +| J.cs:14:66:14:70 | access to parameter field : Object | J.cs:14:50:14:54 | [post] this access [field Field] : Object | +| J.cs:14:73:14:76 | access to parameter prop : Object | J.cs:14:57:14:60 | [post] this access [property Prop] : Object | +| J.cs:14:73:14:76 | access to parameter prop : Object | J.cs:14:57:14:60 | [post] this access [property Prop] : Object | +| J.cs:21:17:21:33 | call to method Source : Object | J.cs:22:34:22:34 | access to local variable o : Object | +| J.cs:21:17:21:33 | call to method Source : Object | J.cs:22:34:22:34 | access to local variable o : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | +| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | +| J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | J.cs:23:14:23:21 | access to property Prop1 | +| J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | J.cs:23:14:23:21 | access to property Prop1 | +| J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | J.cs:27:14:27:21 | access to property Prop1 | +| J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | J.cs:27:14:27:21 | access to property Prop1 | +| J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:30:36:30:52 | call to method Source : Object | J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | +| J.cs:30:36:30:52 | call to method Source : Object | J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | +| J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | J.cs:31:14:31:21 | access to property Prop1 | +| J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | J.cs:31:14:31:21 | access to property Prop1 | +| J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | J.cs:32:14:32:21 | access to property Prop2 | +| J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | J.cs:32:14:32:21 | access to property Prop2 | +| J.cs:41:17:41:33 | call to method Source : Object | J.cs:42:35:42:35 | access to local variable o : Object | +| J.cs:41:17:41:33 | call to method Source : Object | J.cs:42:35:42:35 | access to local variable o : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | +| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | +| J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | J.cs:43:14:43:21 | access to property Prop1 | +| J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | J.cs:43:14:43:21 | access to property Prop1 | +| J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | J.cs:47:14:47:21 | access to property Prop1 | +| J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | J.cs:47:14:47:21 | access to property Prop1 | +| J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:50:36:50:52 | call to method Source : Object | J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | +| J.cs:50:36:50:52 | call to method Source : Object | J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | +| J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | J.cs:51:14:51:21 | access to property Prop1 | +| J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | J.cs:51:14:51:21 | access to property Prop1 | +| J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | J.cs:52:14:52:21 | access to property Prop2 | +| J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | J.cs:52:14:52:21 | access to property Prop2 | +| J.cs:61:17:61:33 | call to method Source : Object | J.cs:62:29:62:29 | access to local variable o : Object | +| J.cs:61:17:61:33 | call to method Source : Object | J.cs:62:29:62:29 | access to local variable o : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | +| J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | J.cs:65:14:65:21 | access to field Field | +| J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | J.cs:65:14:65:21 | access to field Field | +| J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | +| J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | +| J.cs:68:35:68:51 | call to method Source : Object | J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | +| J.cs:68:35:68:51 | call to method Source : Object | J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | +| J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | J.cs:69:14:69:21 | access to field Field | +| J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | J.cs:69:14:69:21 | access to field Field | +| J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | J.cs:70:14:70:20 | access to property Prop | +| J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | J.cs:70:14:70:20 | access to property Prop | +| J.cs:79:17:79:33 | call to method Source : Object | J.cs:80:35:80:35 | access to local variable o : Object | +| J.cs:79:17:79:33 | call to method Source : Object | J.cs:80:35:80:35 | access to local variable o : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | +| J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | J.cs:84:14:84:20 | access to property Prop | +| J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | J.cs:84:14:84:20 | access to property Prop | +| J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | +| J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | +| J.cs:86:36:86:52 | call to method Source : Object | J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | +| J.cs:86:36:86:52 | call to method Source : Object | J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | +| J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | J.cs:87:14:87:21 | access to field Field | +| J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | J.cs:87:14:87:21 | access to field Field | +| J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | J.cs:88:14:88:20 | access to property Prop | +| J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | J.cs:88:14:88:20 | access to property Prop | 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 | @@ -1659,58 +1707,114 @@ 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: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 | -| J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | -| J.cs:40:14:40:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | -| J.cs:40:14:40:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:40:14:40:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | -| J.cs:43:18:43:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | -| J.cs:43:36:43:52 | call to method Source : Object | semmle.label | call to method Source : Object | -| J.cs:43:36:43:52 | call to method Source : Object | semmle.label | call to method Source : Object | -| J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | -| J.cs:44:14:44:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | -| J.cs:44:14:44:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:44:14:44:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | -| J.cs:45:14:45:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | -| J.cs:45:14:45:21 | access to property Prop2 | semmle.label | access to property Prop2 | -| J.cs:45:14:45:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:14:26:14:30 | field : Object | semmle.label | field : Object | +| J.cs:14:26:14:30 | field : Object | semmle.label | field : Object | +| J.cs:14:40:14:43 | prop : Object | semmle.label | prop : Object | +| J.cs:14:40:14:43 | prop : Object | semmle.label | prop : Object | +| J.cs:14:50:14:54 | [post] this access [field Field] : Object | semmle.label | [post] this access [field Field] : Object | +| J.cs:14:50:14:54 | [post] this access [field Field] : Object | semmle.label | [post] this access [field Field] : Object | +| J.cs:14:57:14:60 | [post] this access [property Prop] : Object | semmle.label | [post] this access [property Prop] : Object | +| J.cs:14:57:14:60 | [post] this access [property Prop] : Object | semmle.label | [post] this access [property Prop] : Object | +| J.cs:14:66:14:70 | access to parameter field : Object | semmle.label | access to parameter field : Object | +| J.cs:14:66:14:70 | access to parameter field : Object | semmle.label | access to parameter field : Object | +| J.cs:14:73:14:76 | access to parameter prop : Object | semmle.label | access to parameter prop : Object | +| J.cs:14:73:14:76 | access to parameter prop : Object | semmle.label | access to parameter prop : Object | +| J.cs:21:17:21:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:21:17:21:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object | +| J.cs:22:34:22:34 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:22:34:22:34 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | +| J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | +| J.cs:23:14:23:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:23:14:23:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:27:14:27:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:27:14:27:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:30:36:30:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:30:36:30:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:31:14:31:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:31:14:31:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:32:14:32:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:32:14:32:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:41:17:41:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:41:17:41:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object | +| J.cs:42:35:42:35 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:42:35:42:35 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | +| J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | +| J.cs:43:14:43:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:43:14:43:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:47:14:47:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:47:14:47:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:50:36:50:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:50:36:50:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:51:14:51:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:51:14:51:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:52:14:52:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:52:14:52:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:61:17:61:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:61:17:61:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | semmle.label | object creation of type Struct [field Field] : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | semmle.label | object creation of type Struct [field Field] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | semmle.label | access to local variable s2 [field Field] : Object | +| J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | semmle.label | access to local variable s2 [field Field] : Object | +| J.cs:65:14:65:21 | access to field Field | semmle.label | access to field Field | +| J.cs:65:14:65:21 | access to field Field | semmle.label | access to field Field | +| J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | semmle.label | ... with { ... } [property Prop] : Object | +| J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | semmle.label | ... with { ... } [property Prop] : Object | +| J.cs:68:35:68:51 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:68:35:68:51 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | semmle.label | access to local variable s3 [field Field] : Object | +| J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | semmle.label | access to local variable s3 [field Field] : Object | +| J.cs:69:14:69:21 | access to field Field | semmle.label | access to field Field | +| J.cs:69:14:69:21 | access to field Field | semmle.label | access to field Field | +| J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | +| J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | +| J.cs:70:14:70:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:70:14:70:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:79:17:79:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:79:17:79:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | semmle.label | object creation of type Struct [property Prop] : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | semmle.label | object creation of type Struct [property Prop] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | semmle.label | access to local variable s2 [property Prop] : Object | +| J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | semmle.label | access to local variable s2 [property Prop] : Object | +| J.cs:84:14:84:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:84:14:84:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | semmle.label | ... with { ... } [field Field] : Object | +| J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | semmle.label | ... with { ... } [field Field] : Object | +| J.cs:86:36:86:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:86:36:86:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | semmle.label | access to local variable s3 [field Field] : Object | +| J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | semmle.label | access to local variable s3 [field Field] : Object | +| J.cs:87:14:87:21 | access to field Field | semmle.label | access to field Field | +| J.cs:87:14:87:21 | access to field Field | semmle.label | access to field Field | +| J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | +| J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | +| J.cs:88:14:88:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:88:14:88:20 | access to property Prop | semmle.label | access to property Prop | 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 | @@ -1810,6 +1914,10 @@ subpaths | H.cs:147:25:147:38 | call to method Source : A | H.cs:138:27:138:27 | o : A | H.cs:142:16:142:34 | access to field FieldB : A | H.cs:147:17:147:39 | call to method Through : A | | H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | | H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | J.cs:14:50:14:54 | [post] this access [field Field] : Object | J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | J.cs:14:50:14:54 | [post] this access [field Field] : Object | J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:57:14:60 | [post] this access [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:57:14:60 | [post] this access [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | #select | A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:28 | call to method Source : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:28 | call to method Source : C | call to method Source : C | | A.cs:14:14:14:20 | call to method Get | A.cs:13:15:13:29 | call to method Source : C1 | A.cs:14:14:14:20 | call to method Get | $@ | A.cs:13:15:13:29 | call to method Source : C1 | call to method Source : C1 | @@ -1863,11 +1971,17 @@ 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: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 | -| J.cs:40:14:40:21 | access to property Prop1 | J.cs:34:17:34:33 | call to method Source : Object | J.cs:40:14:40:21 | access to property Prop1 | $@ | J.cs:34:17:34:33 | call to method Source : Object | call to method Source : Object | -| J.cs:44:14:44:21 | access to property Prop1 | J.cs:34:17:34:33 | call to method Source : Object | J.cs:44:14:44:21 | access to property Prop1 | $@ | J.cs:34:17:34:33 | call to method Source : Object | call to method Source : Object | -| J.cs:45:14:45:21 | access to property Prop2 | J.cs:43:36:43:52 | call to method Source : Object | J.cs:45:14:45:21 | access to property Prop2 | $@ | J.cs:43:36:43:52 | call to method Source : Object | call to method Source : Object | +| J.cs:23:14:23:21 | access to property Prop1 | J.cs:21:17:21:33 | call to method Source : Object | J.cs:23:14:23:21 | access to property Prop1 | $@ | J.cs:21:17:21:33 | call to method Source : Object | call to method Source : Object | +| J.cs:27:14:27:21 | access to property Prop1 | J.cs:21:17:21:33 | call to method Source : Object | J.cs:27:14:27:21 | access to property Prop1 | $@ | J.cs:21:17:21:33 | call to method Source : Object | call to method Source : Object | +| J.cs:31:14:31:21 | access to property Prop1 | J.cs:21:17:21:33 | call to method Source : Object | J.cs:31:14:31:21 | access to property Prop1 | $@ | J.cs:21:17:21:33 | call to method Source : Object | call to method Source : Object | +| J.cs:32:14:32:21 | access to property Prop2 | J.cs:30:36:30:52 | call to method Source : Object | J.cs:32:14:32:21 | access to property Prop2 | $@ | J.cs:30:36:30:52 | call to method Source : Object | call to method Source : Object | +| J.cs:43:14:43:21 | access to property Prop1 | J.cs:41:17:41:33 | call to method Source : Object | J.cs:43:14:43:21 | access to property Prop1 | $@ | J.cs:41:17:41:33 | call to method Source : Object | call to method Source : Object | +| J.cs:47:14:47:21 | access to property Prop1 | J.cs:41:17:41:33 | call to method Source : Object | J.cs:47:14:47:21 | access to property Prop1 | $@ | J.cs:41:17:41:33 | call to method Source : Object | call to method Source : Object | +| J.cs:51:14:51:21 | access to property Prop1 | J.cs:41:17:41:33 | call to method Source : Object | J.cs:51:14:51:21 | access to property Prop1 | $@ | J.cs:41:17:41:33 | call to method Source : Object | call to method Source : Object | +| J.cs:52:14:52:21 | access to property Prop2 | J.cs:50:36:50:52 | call to method Source : Object | J.cs:52:14:52:21 | access to property Prop2 | $@ | J.cs:50:36:50:52 | call to method Source : Object | call to method Source : Object | +| J.cs:65:14:65:21 | access to field Field | J.cs:61:17:61:33 | call to method Source : Object | J.cs:65:14:65:21 | access to field Field | $@ | J.cs:61:17:61:33 | call to method Source : Object | call to method Source : Object | +| J.cs:69:14:69:21 | access to field Field | J.cs:61:17:61:33 | call to method Source : Object | J.cs:69:14:69:21 | access to field Field | $@ | J.cs:61:17:61:33 | call to method Source : Object | call to method Source : Object | +| J.cs:70:14:70:20 | access to property Prop | J.cs:68:35:68:51 | call to method Source : Object | J.cs:70:14:70:20 | access to property Prop | $@ | J.cs:68:35:68:51 | call to method Source : Object | call to method Source : Object | +| J.cs:84:14:84:20 | access to property Prop | J.cs:79:17:79:33 | call to method Source : Object | J.cs:84:14:84:20 | access to property Prop | $@ | J.cs:79:17:79:33 | call to method Source : Object | call to method Source : Object | +| J.cs:87:14:87:21 | access to field Field | J.cs:86:36:86:52 | call to method Source : Object | J.cs:87:14:87:21 | access to field Field | $@ | J.cs:86:36:86:52 | call to method Source : Object | call to method Source : Object | +| J.cs:88:14:88:20 | access to property Prop | J.cs:79:17:79:33 | call to method Source : Object | J.cs:88:14:88:20 | access to property Prop | $@ | J.cs:79:17:79: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 71b793646ca..0aeed7eb1a7 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/J.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs @@ -7,6 +7,13 @@ public record class RecordClass(object Prop1, object Prop2) { } public record struct RecordStruct(object Prop1, object Prop2) { } +public struct Struct +{ + public object Field; + public object Prop { get; init; } + public Struct(object field, object prop) => (Field, Prop) = (field, prop); +} + public class J { private void M1() @@ -49,6 +56,42 @@ public class J Sink(r4.Prop2); // no flow } + private void M3() + { + var o = Source(3); + var s1 = new Struct(o, null); + + var s2 = s1 with { }; + Sink(s2.Field); // $ hasValueFlow=3 + Sink(s2.Prop); // no flow + + var s3 = s1 with { Prop = Source(4) }; + Sink(s3.Field); // $ hasValueFlow=3 + Sink(s3.Prop); // $ hasValueFlow=4 + + var s4 = s1 with { Field = null }; + Sink(s4.Field); // no flow + Sink(s4.Prop); // no flow + } + + private void M4() + { + var o = Source(5); + var s1 = new Struct(null, o); + + var s2 = s1 with { }; + Sink(s2.Field); // $ no flow + Sink(s2.Prop); // $ hasValueFlow=5 + + var s3 = s1 with { Field = Source(6) }; + Sink(s3.Field); // $ hasValueFlow=6 + Sink(s3.Prop); // $ hasValueFlow=5 + + var s4 = s1 with { Prop = null }; + Sink(s4.Field); // no flow + Sink(s4.Prop); // no flow + } + public static void Sink(object o) { } static T Source(object source) => throw null; From 77c2b43560dcf07407cb29ce279d9065437a6181 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 15 Nov 2021 15:55:28 +0100 Subject: [PATCH 138/196] Add change note and severity score --- java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql | 1 + .../change-notes/2021-11-15-insecure-trustamanger-query.md | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 java/ql/src/change-notes/2021-11-15-insecure-trustamanger-query.md diff --git a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql index 3f7f6e3b705..bb3fc7bfb49 100644 --- a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql +++ b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql @@ -3,6 +3,7 @@ * @description Trusting all certificates allows an attacker to perform a machine-in-the-middle attack. * @kind path-problem * @problem.severity error + * @security-severity 7.5 * @precision high * @id java/insecure-trustmanager * @tags security diff --git a/java/ql/src/change-notes/2021-11-15-insecure-trustamanger-query.md b/java/ql/src/change-notes/2021-11-15-insecure-trustamanger-query.md new file mode 100644 index 00000000000..7789ebe3c25 --- /dev/null +++ b/java/ql/src/change-notes/2021-11-15-insecure-trustamanger-query.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* The query "`TrustManager` that accepts all certificates" (`java/insecure-trustmanager`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @intrigus-lgtm](https://github.com/github/codeql/pull/4879). From 7a1a45f5f9b5d705e47b83693cb7fa81a20ed23f Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 15 Nov 2021 16:41:17 +0100 Subject: [PATCH 139/196] QLDoc --- java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll b/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll index f8b4dca8a4e..3a9b80edc0f 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll @@ -1,3 +1,5 @@ +/** Provides classes and predicates to reason about insecure `TrustManager`s. */ + import java private import semmle.code.java.controlflow.Guards private import semmle.code.java.security.Encryption From c105d719523dd1bf680c320dbba5845c915fc657 Mon Sep 17 00:00:00 2001 From: mc <42146119+mchammer01@users.noreply.github.com> Date: Mon, 22 Nov 2021 11:35:09 +0000 Subject: [PATCH 140/196] Update InsecureTrustManager.qhelp Fixed typos and carried out and editorial review --- java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp index 99746477a34..349c7640b5f 100644 --- a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp +++ b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp @@ -4,8 +4,8 @@

    -If the checkServerTrusted method of a TrustManager never throws a CertificateException it trusts every certificate. -This allows an attacker to perform a machine-in-the-middle attack against the application therefore breaking any security Transport Layer Security (TLS) gives. +If the checkServerTrusted method of a TrustManager never throws a CertificateException, it trusts every certificate. +This allows an attacker to perform a machine-in-the-middle attack against the application, therefore breaking any security Transport Layer Security (TLS) gives.

    @@ -42,6 +42,6 @@ is loaded into a KeyStore. This explicitly defines the certificate -

  • Android Develoers:Security with HTTPS and SSL.
  • +
  • Android Developers: Security with HTTPS and SSL.
  • From 967308fbfda50db4ec66634b82258828bb539461 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 20 Jan 2022 10:22:26 +0100 Subject: [PATCH 141/196] Change InsecureTrustManagerConfiguration to DataFlow --- .../security/InsecureTrustManagerQuery.qll | 9 ++++-- .../InsecureTrustManagerTest.java | 30 +++++++++---------- .../InsecureTrustManagerTest.ql | 4 +-- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll index 7d9bee65e50..6c92570633d 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll @@ -2,14 +2,13 @@ import java import semmle.code.java.dataflow.FlowSources -import semmle.code.java.security.Encryption import semmle.code.java.security.InsecureTrustManager /** * A configuration to model the flow of an insecure `TrustManager` * to the initialization of an SSL context. */ -class InsecureTrustManagerConfiguration extends TaintTracking::Configuration { +class InsecureTrustManagerConfiguration extends DataFlow::Configuration { InsecureTrustManagerConfiguration() { this = "InsecureTrustManagerConfiguration" } override predicate isSource(DataFlow::Node source) { @@ -17,4 +16,10 @@ class InsecureTrustManagerConfiguration extends TaintTracking::Configuration { } override predicate isSink(DataFlow::Node sink) { sink instanceof InsecureTrustManagerSink } + + override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) { + (this.isSink(node) or this.isAdditionalFlowStep(node, _)) and + node.getType() instanceof Array and + c instanceof DataFlow::ArrayContent + } } diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java index ba15609c655..17e8fc60afc 100644 --- a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java @@ -121,7 +121,7 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } private static void namedVariableFlagDirectInsecureTrustManagerCall() @@ -145,7 +145,7 @@ public class InsecureTrustManagerTest { if (SOME_NAME_THAT_IS_NOT_A_FLAG_NAME) { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } } @@ -177,7 +177,7 @@ public class InsecureTrustManagerTest { if (Boolean.parseBoolean(System.getProperty("SOME_NAME_THAT_IS_NOT_A_FLAG_NAME"))) { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } } @@ -209,7 +209,7 @@ public class InsecureTrustManagerTest { if (is42TheAnswerForEverything()) { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } } @@ -226,7 +226,7 @@ public class InsecureTrustManagerTest { if (schemaFromHttpRequest.equalsIgnoreCase("https")) { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } } @@ -244,7 +244,7 @@ public class InsecureTrustManagerTest { if (!schemaFromHttpRequest.equalsIgnoreCase("https")) { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } } @@ -264,7 +264,7 @@ public class InsecureTrustManagerTest { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } @@ -276,7 +276,7 @@ public class InsecureTrustManagerTest { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } @@ -288,7 +288,7 @@ public class InsecureTrustManagerTest { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } @@ -300,7 +300,7 @@ public class InsecureTrustManagerTest { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } @@ -312,7 +312,7 @@ public class InsecureTrustManagerTest { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } @@ -324,7 +324,7 @@ public class InsecureTrustManagerTest { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } private static void isEqualsIgnoreCaseNOTGuardingDirectInsecureTrustManagerCall() @@ -336,7 +336,7 @@ public class InsecureTrustManagerTest { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } @@ -349,7 +349,7 @@ public class InsecureTrustManagerTest { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } @@ -357,6 +357,6 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { SSLContext context = SSLContext.getInstance("TLS"); TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; - context.init(null, trustManager, null); // $ hasTaintFlow + context.init(null, trustManager, null); // $ hasValueFlow } } diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql index 3f83c2ee78c..b2922d13d69 100644 --- a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql @@ -3,9 +3,7 @@ import semmle.code.java.security.InsecureTrustManagerQuery import TestUtilities.InlineFlowTest class InsecureTrustManagerTest extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { none() } - - override TaintTracking::Configuration getTaintFlowConfig() { + override DataFlow::Configuration getValueFlowConfig() { result = any(InsecureTrustManagerConfiguration c) } } From 4e8e3a74209c421c679aa27a540e0f348b7f603d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 20 Jan 2022 10:41:35 +0100 Subject: [PATCH 142/196] simplify expressions that could be type-casts --- cpp/ql/lib/semmle/code/cpp/Class.qll | 8 ++-- cpp/ql/lib/semmle/code/cpp/Specifier.qll | 4 +- cpp/ql/lib/semmle/code/cpp/XML.qll | 2 +- .../semmle/code/cpp/controlflow/IRGuards.qll | 4 +- .../cpp/dataflow/internal/DataFlowPrivate.qll | 2 +- cpp/ql/lib/semmle/code/cpp/exprs/Access.qll | 12 +++--- cpp/ql/lib/semmle/code/cpp/exprs/Call.qll | 2 +- cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll | 4 +- .../semmle/code/cpp/metrics/MetricClass.qll | 40 +++++++++---------- .../lib/semmle/code/cpp/padding/Padding.qll | 2 +- .../lib/semmle/code/cpp/pointsto/PointsTo.qll | 2 +- .../code/cpp/security/TaintTrackingImpl.qll | 2 +- cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll | 4 +- cpp/ql/src/Critical/DeadCodeGoto.ql | 4 +- cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll | 6 +-- .../CWE-732/UnsafeDaclSecurityDescriptor.ql | 4 +- .../CWE/CWE-1041/FindWrapperFunctions.ql | 10 ++--- .../Security/CWE/CWE-675/DoubleRelease.ql | 4 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql | 2 +- csharp/ql/lib/Linq/Helpers.qll | 2 +- csharp/ql/lib/semmle/code/csharp/XML.qll | 2 +- .../semmle/code/csharp/dispatch/Dispatch.qll | 2 +- .../src/Likely Bugs/Statements/UseBraces.ql | 4 +- .../src/experimental/ir/internal/IRGuards.qll | 4 +- .../writing-codeql-queries/river-crossing.ql | 3 +- java/ql/lib/semmle/code/java/Expr.qll | 4 +- java/ql/lib/semmle/code/java/Generics.qll | 2 +- java/ql/lib/semmle/code/java/Statement.qll | 4 +- .../java/controlflow/UnreachableBlocks.qll | 2 +- .../semmle/code/java/dataflow/FlowSources.qll | 2 +- .../code/java/deadcode/DeadEnumConstant.qll | 2 +- .../deadcode/frameworks/CamelEntryPoints.qll | 2 +- .../semmle/code/java/frameworks/Mockito.qll | 2 +- .../java/frameworks/spring/SpringBean.qll | 2 +- .../java/frameworks/spring/SpringBeanFile.qll | 6 +-- .../frameworks/spring/SpringXMLElement.qll | 2 +- .../code/java/metrics/MetricElement.qll | 4 +- .../semmle/code/java/metrics/MetricStmt.qll | 2 +- .../security/UnsafeDeserializationQuery.qll | 2 +- java/ql/lib/semmle/code/xml/XML.qll | 2 +- .../UnusedMavenDependencyBinary.ql | 2 +- java/ql/src/DeadCode/DeadField.ql | 7 +--- .../UseSetterInjection.ql | 2 +- .../UseShortcutForms.ql | 12 +++--- .../Likely Bugs/Cloning/MissingMethodClone.ql | 2 +- .../Concurrency/WaitOutsideLoop.ql | 2 +- .../IncorrectSerialVersionUID.ql | 2 +- .../NonSerializableInnerClass.ql | 2 +- .../Implementation Hiding/StaticArray.ql | 2 +- .../CWE-094/SpringImplicitViewManipulation.ql | 2 +- .../CWE/CWE-200/AndroidFileIntentSource.qll | 4 +- .../CWE/CWE-326/InsufficientKeySize.ql | 4 +- javascript/ql/lib/semmle/javascript/XML.qll | 2 +- .../semmle/javascript/frameworks/Files.qll | 4 +- .../CWE-020/PostMessageNoOriginCheck.ql | 4 +- .../testUtilities/ConsistencyChecking.qll | 4 +- python/ql/lib/semmle/python/Comment.qll | 2 +- python/ql/lib/semmle/python/Function.qll | 2 +- python/ql/lib/semmle/python/Variables.qll | 4 +- .../dataflow/new/internal/PrintNode.qll | 2 +- .../lib/semmle/python/pointsto/PointsTo.qll | 2 +- .../ql/lib/semmle/python/types/Exceptions.qll | 4 +- python/ql/lib/semmle/python/xml/XML.qll | 2 +- .../MismatchInMultipleAssignment.ql | 2 +- python/ql/src/Variables/UndefinedExport.ql | 2 +- python/ql/src/Variables/UndefinedGlobal.ql | 2 +- python/ql/src/analysis/Efficiency.ql | 2 +- .../codeql/ruby/frameworks/ActiveRecord.qll | 4 +- .../ruby/frameworks/http_clients/Httparty.qll | 2 +- .../security/cwe-732/WeakFilePermissions.ql | 2 +- 70 files changed, 123 insertions(+), 143 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/Class.qll b/cpp/ql/lib/semmle/code/cpp/Class.qll index 4fe1b07e32a..64819a5e945 100644 --- a/cpp/ql/lib/semmle/code/cpp/Class.qll +++ b/cpp/ql/lib/semmle/code/cpp/Class.qll @@ -206,9 +206,7 @@ class Class extends UserType { * it is callable by a particular caller. For C++11, there's also a question * of whether to include members that are defaulted or deleted. */ - deprecated predicate hasCopyConstructor() { - exists(CopyConstructor cc | cc = this.getAMemberFunction()) - } + deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor } /** * Holds if this class has a copy assignment operator that is either @@ -224,7 +222,7 @@ class Class extends UserType { * or deleted. */ deprecated predicate hasCopyAssignmentOperator() { - exists(CopyAssignmentOperator coa | coa = this.getAMemberFunction()) + this.getAMemberFunction() instanceof CopyAssignmentOperator } /** @@ -887,7 +885,7 @@ class NestedClass extends Class { * pure virtual function. */ class AbstractClass extends Class { - AbstractClass() { exists(PureVirtualFunction f | this.getAMemberFunction() = f) } + AbstractClass() { this.getAMemberFunction() instanceof PureVirtualFunction } override string getAPrimaryQlClass() { result = "AbstractClass" } } diff --git a/cpp/ql/lib/semmle/code/cpp/Specifier.qll b/cpp/ql/lib/semmle/code/cpp/Specifier.qll index fe2919c3ed6..69cccf06ffb 100644 --- a/cpp/ql/lib/semmle/code/cpp/Specifier.qll +++ b/cpp/ql/lib/semmle/code/cpp/Specifier.qll @@ -286,13 +286,13 @@ class AttributeArgument extends Element, @attribute_arg { override Location getLocation() { attribute_args(underlyingElement(this), _, _, _, result) } override string toString() { - if exists(@attribute_arg_empty self | self = underlyingElement(this)) + if underlyingElement(this) instanceof @attribute_arg_empty then result = "empty argument" else exists(string prefix, string tail | (if exists(this.getName()) then prefix = this.getName() + "=" else prefix = "") and ( - if exists(@attribute_arg_type self | self = underlyingElement(this)) + if underlyingElement(this) instanceof @attribute_arg_type then tail = this.getValueType().getName() else tail = this.getValueText() ) and diff --git a/cpp/ql/lib/semmle/code/cpp/XML.qll b/cpp/ql/lib/semmle/code/cpp/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/cpp/ql/lib/semmle/code/cpp/XML.qll +++ b/cpp/ql/lib/semmle/code/cpp/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll index 9aee2556c1d..2b222376a0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll @@ -29,7 +29,7 @@ class GuardCondition extends Expr { exists(IRGuardCondition ir | this = ir.getUnconvertedResultExpression()) or // no binary operators in the IR - exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) + this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition or // the IR short-circuits if(!x) // don't produce a guard condition for `y = !x` and other non-short-circuited cases @@ -98,7 +98,7 @@ class GuardCondition extends Expr { */ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { GuardConditionFromBinaryLogicalOperator() { - exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) + this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition } override predicate controls(BasicBlock controlled, boolean testIsTrue) { diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index c7bdcb3169e..0a44ec3336b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -48,7 +48,7 @@ private class Argument extends Expr { */ class ArgumentNode extends Node { ArgumentNode() { - exists(Argument arg | this.asExpr() = arg) or + this.asExpr() instanceof Argument or this = getInstanceArgument(_) } diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll index 35cf1974127..04e7376b11d 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll @@ -84,8 +84,8 @@ class VariableAccess extends Access, @varaccess { exists(Assignment a | a.getLValue() = this) or exists(CrementOperation c | c.getOperand() = this) or exists(AddressOfExpr addof | addof.getOperand() = this) or - exists(ReferenceToExpr rte | this.getConversion() = rte) or - exists(ArrayToPointerConversion atpc | this.getConversion() = atpc) + this.getConversion() instanceof ReferenceToExpr or + this.getConversion() instanceof ArrayToPointerConversion } /** @@ -104,8 +104,8 @@ class VariableAccess extends Access, @varaccess { predicate isRValue() { not exists(AssignExpr ae | ae.getLValue() = this) and not exists(AddressOfExpr addof | addof.getOperand() = this) and - not exists(ReferenceToExpr rte | this.getConversion() = rte) and - not exists(ArrayToPointerConversion atpc | this.getConversion() = atpc) + not this.getConversion() instanceof ReferenceToExpr and + not this.getConversion() instanceof ArrayToPointerConversion } /** @@ -218,9 +218,7 @@ class PointerFieldAccess extends FieldAccess { class DotFieldAccess extends FieldAccess { override string getAPrimaryQlClass() { result = "DotFieldAccess" } - DotFieldAccess() { - exists(Class c | c = this.getQualifier().getFullyConverted().getUnspecifiedType()) - } + DotFieldAccess() { this.getQualifier().getFullyConverted().getUnspecifiedType() instanceof Class } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll index b4761dffe9a..7ceda8ddbff 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll @@ -35,7 +35,7 @@ class Call extends Expr, NameQualifiableElement, TCall { * * For example, `ptr->f()` has a qualifier, whereas plain `f()` does not. */ - predicate hasQualifier() { exists(Expr e | this.getChild(-1) = e) } + predicate hasQualifier() { exists(this.getChild(-1)) } /** * Gets the expression to the left of the function name or function pointer variable name. diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll index 273023a8229..701cfbfd636 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll @@ -724,7 +724,7 @@ class SizeofOperator extends Expr, @runtime_sizeof { * ``` */ class SizeofExprOperator extends SizeofOperator { - SizeofExprOperator() { exists(Expr e | this.getChild(0) = e) } + SizeofExprOperator() { exists(this.getChild(0)) } override string getAPrimaryQlClass() { result = "SizeofExprOperator" } @@ -787,7 +787,7 @@ class AlignofOperator extends Expr, @runtime_alignof { * ``` */ class AlignofExprOperator extends AlignofOperator { - AlignofExprOperator() { exists(Expr e | this.getChild(0) = e) } + AlignofExprOperator() { exists(this.getChild(0)) } /** * Gets the contained expression. diff --git a/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll b/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll index 496e3f4511d..f1295169b5d 100644 --- a/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll +++ b/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll @@ -308,45 +308,45 @@ class MetricClass extends Class { } private string getAUsedHalsteadN1Operator() { - exists(CommaExpr e | e = this.getAnEnclosedExpression()) and result = "comma" + this.getAnEnclosedExpression() instanceof CommaExpr and result = "comma" or - exists(ReferenceToExpr e | e = this.getAnEnclosedExpression()) and result = "refTo" + this.getAnEnclosedExpression() instanceof ReferenceToExpr and result = "refTo" or - exists(PointerDereferenceExpr e | e = this.getAnEnclosedExpression()) and result = "dereference" + this.getAnEnclosedExpression() instanceof PointerDereferenceExpr and result = "dereference" or - exists(CStyleCast e | e = this.getAnEnclosedExpression()) and result = "cCast" + this.getAnEnclosedExpression() instanceof CStyleCast and result = "cCast" or - exists(StaticCast e | e = this.getAnEnclosedExpression()) and result = "staticCast" + this.getAnEnclosedExpression() instanceof StaticCast and result = "staticCast" or - exists(ConstCast e | e = this.getAnEnclosedExpression()) and result = "constCast" + this.getAnEnclosedExpression() instanceof ConstCast and result = "constCast" or - exists(ReinterpretCast e | e = this.getAnEnclosedExpression()) and result = "reinterpretCast" + this.getAnEnclosedExpression() instanceof ReinterpretCast and result = "reinterpretCast" or - exists(DynamicCast e | e = this.getAnEnclosedExpression()) and result = "dynamicCast" + this.getAnEnclosedExpression() instanceof DynamicCast and result = "dynamicCast" or - exists(SizeofExprOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofExpr" + this.getAnEnclosedExpression() instanceof SizeofExprOperator and result = "sizeofExpr" or - exists(SizeofTypeOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofType" + this.getAnEnclosedExpression() instanceof SizeofTypeOperator and result = "sizeofType" or - exists(IfStmt e | e = this.getAnEnclosedStmt()) and result = "ifVal" + this.getAnEnclosedStmt() instanceof IfStmt and result = "ifVal" or - exists(SwitchStmt e | e = this.getAnEnclosedStmt()) and result = "switchVal" + this.getAnEnclosedStmt() instanceof SwitchStmt and result = "switchVal" or - exists(ForStmt e | e = this.getAnEnclosedStmt()) and result = "forVal" + this.getAnEnclosedStmt() instanceof ForStmt and result = "forVal" or - exists(DoStmt e | e = this.getAnEnclosedStmt()) and result = "doVal" + this.getAnEnclosedStmt() instanceof DoStmt and result = "doVal" or - exists(WhileStmt e | e = this.getAnEnclosedStmt()) and result = "whileVal" + this.getAnEnclosedStmt() instanceof WhileStmt and result = "whileVal" or - exists(GotoStmt e | e = this.getAnEnclosedStmt()) and result = "gotoVal" + this.getAnEnclosedStmt() instanceof GotoStmt and result = "gotoVal" or - exists(ContinueStmt e | e = this.getAnEnclosedStmt()) and result = "continueVal" + this.getAnEnclosedStmt() instanceof ContinueStmt and result = "continueVal" or - exists(BreakStmt e | e = this.getAnEnclosedStmt()) and result = "breakVal" + this.getAnEnclosedStmt() instanceof BreakStmt and result = "breakVal" or - exists(ReturnStmt e | e = this.getAnEnclosedStmt()) and result = "returnVal" + this.getAnEnclosedStmt() instanceof ReturnStmt and result = "returnVal" or - exists(SwitchCase e | e = this.getAnEnclosedStmt()) and result = "caseVal" + this.getAnEnclosedStmt() instanceof SwitchCase and result = "caseVal" or exists(IfStmt s | s = this.getAnEnclosedStmt() and s.hasElse()) and result = "elseVal" diff --git a/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll b/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll index c5c1903b4d1..3375383f2ea 100644 --- a/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll +++ b/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll @@ -397,7 +397,7 @@ class PaddedType extends Class { // Support only single inheritance for now. If multiple inheritance is // supported, be sure to fix up the calls to getABaseClass*() to correctly // handle the presence of multiple base class subojects with the same type. - not exists(ClassDerivation cd | cd = this.getDerivation(1)) + not exists(this.getDerivation(1)) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/pointsto/PointsTo.qll b/cpp/ql/lib/semmle/code/cpp/pointsto/PointsTo.qll index a9802fad4b7..83b8c2936f0 100644 --- a/cpp/ql/lib/semmle/code/cpp/pointsto/PointsTo.qll +++ b/cpp/ql/lib/semmle/code/cpp/pointsto/PointsTo.qll @@ -72,7 +72,7 @@ predicate lvalue(Element e) { or exists(Cast c | lvalue(c) and e.(Expr).getConversion() = c) or - exists(ReferenceToExpr toref | e.(Expr).getConversion() = toref) + e.(Expr).getConversion() instanceof ReferenceToExpr or // If f is a function-pointer, then the following two // calls are equivalent: f() and (*f)() diff --git a/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll index 00db6a18bcb..01230e6880c 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll @@ -258,7 +258,7 @@ private predicate insideFunctionValueMoveTo(Element src, Element dest) { format.getConversionChar(sourceArg - ffc.getTarget().getNumberOfParameters()) = ["s", "S"] ) or - not exists(FormatLiteral fl | fl = c.(FormattingFunctionCall).getFormat()) + not c.(FormattingFunctionCall).getFormat() instanceof FormatLiteral or not c instanceof FormattingFunctionCall ) and diff --git a/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll b/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll index af68daf025c..5b157a54ce8 100644 --- a/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll @@ -271,7 +271,7 @@ class IfStmt extends ConditionalStmt, @stmt_if { * if (b) { x = 1; } * ``` */ - predicate hasElse() { exists(Stmt s | this.getElse() = s) } + predicate hasElse() { exists(this.getElse()) } override string toString() { result = "if (...) ... " } @@ -357,7 +357,7 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if { * if constexpr (b) { x = 1; } * ``` */ - predicate hasElse() { exists(Stmt s | this.getElse() = s) } + predicate hasElse() { exists(this.getElse()) } override string toString() { result = "if constexpr (...) ... " } diff --git a/cpp/ql/src/Critical/DeadCodeGoto.ql b/cpp/ql/src/Critical/DeadCodeGoto.ql index a2f8db771b0..425a39c74ca 100644 --- a/cpp/ql/src/Critical/DeadCodeGoto.ql +++ b/cpp/ql/src/Critical/DeadCodeGoto.ql @@ -30,8 +30,8 @@ where // the next statement isn't breaking out of a switch not s.(BreakStmt).getBreakable() instanceof SwitchStmt and // the next statement isn't a loop that can be jumped into - not exists(LabelStmt ls | s.(Loop).getStmt().getAChild*() = ls) and - not exists(SwitchCase sc | s.(Loop).getStmt().getAChild*() = sc) and + not s.(Loop).getStmt().getAChild*() instanceof LabelStmt and + not s.(Loop).getStmt().getAChild*() instanceof SwitchCase and // no preprocessor logic applies not functionContainsPreprocCode(js.getEnclosingFunction()) select js, "This statement makes $@ unreachable.", s, s.toString() diff --git a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll index 29da7321603..719c16281f2 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll +++ b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll @@ -55,7 +55,7 @@ abstract class LeapYearFieldAccess extends YearFieldAccess { op.getAnOperand() = this and ( op instanceof AssignArithmeticOperation or - exists(BinaryArithmeticOperation bao | bao = op.getAnOperand()) or + op.getAnOperand() instanceof BinaryArithmeticOperation or op instanceof CrementOperation ) ) @@ -212,9 +212,7 @@ class ChecksForLeapYearFunctionCall extends FunctionCall { class LeapYearCheckConfiguration extends DataFlow::Configuration { LeapYearCheckConfiguration() { this = "LeapYearCheckConfiguration" } - override predicate isSource(DataFlow::Node source) { - exists(VariableAccess va | va = source.asExpr()) - } + override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess } override predicate isSink(DataFlow::Node sink) { exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument()) diff --git a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql index bf673826347..81998bda450 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql @@ -34,9 +34,7 @@ class SetSecurityDescriptorDaclFunctionCall extends FunctionCall { class NullDaclConfig extends DataFlow::Configuration { NullDaclConfig() { this = "NullDaclConfig" } - override predicate isSource(DataFlow::Node source) { - exists(NullValue nullExpr | source.asExpr() = nullExpr) - } + override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } override predicate isSink(DataFlow::Node sink) { exists(SetSecurityDescriptorDaclFunctionCall call, VariableAccess val | val = sink.asExpr() | diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql index 4b147fa3612..106369e9319 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql @@ -24,10 +24,10 @@ class CallUsedToHandleErrors extends FunctionCall { not exists(this.(ControlFlowNode).getASuccessor()) or // call throwing an exception - exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor()) + this.(ControlFlowNode).getASuccessor() instanceof ThrowExpr or // call logging a message, possibly an error - exists(FormattingFunction ff | ff = this.(ControlFlowNode).getASuccessor()) + this.(ControlFlowNode).getASuccessor() instanceof FormattingFunction or // enabling recursive search exists(CallUsedToHandleErrors fr | getTarget() = fr.getEnclosingFunction()) @@ -37,9 +37,9 @@ class CallUsedToHandleErrors extends FunctionCall { /** Holds if the conditions for a call outside the wrapper function are met. */ predicate conditionsOutsideWrapper(FunctionCall fcp) { fcp.getNumberOfArguments() > 0 and - not exists(ConditionalStmt cdtmp | fcp.getEnclosingStmt().getParentStmt*() = cdtmp) and - not exists(Loop lptmp | fcp.getEnclosingStmt().getParentStmt*() = lptmp) and - not exists(ReturnStmt rttmp | fcp.getEnclosingStmt().getParentStmt*() = rttmp) and + not fcp.getEnclosingStmt().getParentStmt*() instanceof ConditionalStmt and + not fcp.getEnclosingStmt().getParentStmt*() instanceof Loop and + not fcp.getEnclosingStmt().getParentStmt*() instanceof ReturnStmt and not exists(FunctionCall fctmp2 | fcp = fctmp2.getAnArgument().getAChild*()) and not exists(Assignment astmp | fcp = astmp.getRValue().getAChild*()) and not exists(Initializer intmp | fcp = intmp.getExpr().getAChild*()) and diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql b/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql index 474f00acc55..7a884769bf8 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql @@ -26,7 +26,7 @@ class CallMayNotReturn extends FunctionCall { // call to another function that may not return exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction()) or - exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor()) + this.(ControlFlowNode).getASuccessor() instanceof ThrowExpr } } @@ -127,7 +127,7 @@ predicate similarArguments(FunctionCall fc, FunctionCall fc1) { from FunctionCall fc, FunctionCall fc1 where - not exists(CallMayNotReturn fctmp | fctmp = fc.getASuccessor*()) and + not fc.getASuccessor*() instanceof CallMayNotReturn and not exists(IfStmt ifs | ifs.getCondition().getAChild*() = fc) and ( // detecting a repeated call situation within one function diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql index 090eb0baa67..13d81cebf2b 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql @@ -15,6 +15,6 @@ from EqualityOperation e, PointerToMemberType t, Class c where e.getAnOperand().getType() = t and t.getClass() = c and - exists(VirtualFunction f | c.getAMemberFunction() = f) + c.getAMemberFunction() instanceof VirtualFunction select e, "AV Rule 97.1: Neither operand of an equality operator shall be a pointer to a virtual member function." diff --git a/csharp/ql/lib/Linq/Helpers.qll b/csharp/ql/lib/Linq/Helpers.qll index dc347c2f0d3..a3c5667c8bb 100644 --- a/csharp/ql/lib/Linq/Helpers.qll +++ b/csharp/ql/lib/Linq/Helpers.qll @@ -46,7 +46,7 @@ predicate missedAllOpportunity(ForeachStmt fes) { bl = a.getRValue() and bl.toString() = "false" ) and - exists(BreakStmt bs | bs = is.getThen().getAChild*()) + is.getThen().getAChild*() instanceof BreakStmt ) } diff --git a/csharp/ql/lib/semmle/code/csharp/XML.qll b/csharp/ql/lib/semmle/code/csharp/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/csharp/ql/lib/semmle/code/csharp/XML.qll +++ b/csharp/ql/lib/semmle/code/csharp/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index 1fbba72f864..4d994ed2afb 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -292,7 +292,7 @@ private module Internal { pragma[nomagic] predicate hasSubsumedQualifierTypeOverridden(Gvn::GvnType t, OverridableCallable c) { this.hasSubsumedQualifierType(t) and - hasCallable(t, c, any(OverridableCallable oc | oc = this.getAStaticTargetExt())) + hasCallable(t, c, this.getAStaticTargetExt()) } /** diff --git a/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql b/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql index 900ded8ddb6..4b3fa2096a7 100755 --- a/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql +++ b/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql @@ -26,11 +26,11 @@ Stmt getASuccessorStmt(Stmt s) { } class IfThenStmt extends IfStmt { - IfThenStmt() { not exists(Stmt s | getElse() = s) } + IfThenStmt() { not exists(getElse()) } } class IfThenElseStmt extends IfStmt { - IfThenElseStmt() { exists(Stmt s | getElse() = s) } + IfThenElseStmt() { exists(getElse()) } } Stmt getTrailingBody(Stmt s) { diff --git a/csharp/ql/src/experimental/ir/internal/IRGuards.qll b/csharp/ql/src/experimental/ir/internal/IRGuards.qll index c5351e14d5e..a87788eb9a0 100644 --- a/csharp/ql/src/experimental/ir/internal/IRGuards.qll +++ b/csharp/ql/src/experimental/ir/internal/IRGuards.qll @@ -24,7 +24,7 @@ class GuardCondition extends Expr { exists(IRGuardCondition ir | this = ir.getUnconvertedResultExpression()) or // no binary operators in the IR - exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) + this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition or // the IR short-circuits if(!x) // don't produce a guard condition for `y = !x` and other non-short-circuited cases @@ -124,7 +124,7 @@ private predicate impliesValue( */ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { GuardConditionFromBinaryLogicalOperator() { - exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) + this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition } override predicate controls(BasicBlock controlled, boolean testIsTrue) { diff --git a/docs/codeql/writing-codeql-queries/river-crossing.ql b/docs/codeql/writing-codeql-queries/river-crossing.ql index 6b0e5cfe2a3..397ac7e39f8 100644 --- a/docs/codeql/writing-codeql-queries/river-crossing.ql +++ b/docs/codeql/writing-codeql-queries/river-crossing.ql @@ -95,7 +95,7 @@ class State extends string { exists(string pathSoFar, string visitedStatesSoFar, Cargo cargo | result = this.reachesVia(pathSoFar, visitedStatesSoFar).safeFerry(cargo) and // The resulting state has not yet been visited. - not exists(int i | i = visitedStatesSoFar.indexOf(result)) and + not exists(visitedStatesSoFar.indexOf(result)) and visitedStates = visitedStatesSoFar + "/" + result and path = pathSoFar + "\n Ferry " + cargo ) @@ -115,4 +115,3 @@ class GoalState extends State { from string path where any(InitialState i).reachesVia(path, _) = any(GoalState g) select path - diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index a4158696b3c..58b8954d1e2 100755 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1750,7 +1750,7 @@ class TypeAccess extends Expr, Annotatable, @typeaccess { Expr getQualifier() { result.isNthChildOf(this, -1) } /** Holds if this type access has a qualifier. */ - predicate hasQualifier() { exists(Expr e | e = this.getQualifier()) } + predicate hasQualifier() { exists(this.getQualifier()) } /** Gets a type argument supplied to this type access. */ Expr getATypeArgument() { result.getIndex() >= 0 and result.getParent() = this } @@ -1762,7 +1762,7 @@ class TypeAccess extends Expr, Annotatable, @typeaccess { } /** Holds if this type access has a type argument. */ - predicate hasTypeArgument() { exists(Expr e | e = this.getATypeArgument()) } + predicate hasTypeArgument() { exists(this.getATypeArgument()) } /** Gets the compilation unit in which this type access occurs. */ override CompilationUnit getCompilationUnit() { result = Expr.super.getCompilationUnit() } diff --git a/java/ql/lib/semmle/code/java/Generics.qll b/java/ql/lib/semmle/code/java/Generics.qll index e1bf32d475b..95471437988 100755 --- a/java/ql/lib/semmle/code/java/Generics.qll +++ b/java/ql/lib/semmle/code/java/Generics.qll @@ -101,7 +101,7 @@ class GenericInterface extends GenericType, Interface { */ abstract class BoundedType extends RefType, @boundedtype { /** Holds if this type is bounded. */ - predicate hasTypeBound() { exists(TypeBound tb | tb = this.getATypeBound()) } + predicate hasTypeBound() { exists(this.getATypeBound()) } /** Gets a type bound for this type, if any. */ TypeBound getATypeBound() { result.getBoundedType() = this } diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index 082fb2ab295..31c81f46c0f 100755 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -636,7 +636,7 @@ class BreakStmt extends Stmt, @breakstmt { string getLabel() { namestrings(result, _, this) } /** Holds if this `break` statement has an explicit label. */ - predicate hasLabel() { exists(string s | s = this.getLabel()) } + predicate hasLabel() { exists(this.getLabel()) } override string pp() { if this.hasLabel() then result = "break " + this.getLabel() else result = "break" @@ -673,7 +673,7 @@ class ContinueStmt extends Stmt, @continuestmt { string getLabel() { namestrings(result, _, this) } /** Holds if this `continue` statement has an explicit label. */ - predicate hasLabel() { exists(string s | s = this.getLabel()) } + predicate hasLabel() { exists(this.getLabel()) } override string pp() { if this.hasLabel() then result = "continue " + this.getLabel() else result = "continue" diff --git a/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll b/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll index 8e9d90769f3..055671f7592 100644 --- a/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll +++ b/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll @@ -212,7 +212,7 @@ class UnreachableBasicBlock extends BasicBlock { not exists(Callable c | c.getBody() = this) and not this instanceof Callable and not exists(Annotation a | a.getAChildExpr*() = this) and - not exists(AssertStmt a | a = this.(Expr).getEnclosingStmt()) and + not this.(Expr).getEnclosingStmt() instanceof AssertStmt and not this instanceof CatchClause or // Switch statements with a constant comparison expression may have unreachable cases. diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll index d8d02f995a6..af36ff7a41c 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll @@ -109,7 +109,7 @@ private class MessageBodyReaderParameterSource extends RemoteFlowSource { } private class PlayParameterSource extends RemoteFlowSource { - PlayParameterSource() { exists(PlayActionMethodQueryParameter p | p = this.asParameter()) } + PlayParameterSource() { this.asParameter() instanceof PlayActionMethodQueryParameter } override string getSourceType() { result = "Play Query Parameters" } } diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadEnumConstant.qll b/java/ql/lib/semmle/code/java/deadcode/DeadEnumConstant.qll index 13efdce9a9d..17c8e09eabb 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadEnumConstant.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadEnumConstant.qll @@ -60,7 +60,7 @@ predicate exception(EnumConstant e) { ) or // Entire `Enum` annotated with reflective annotation. - exists(ReflectiveAccessAnnotation ann | ann = t.getAnAnnotation()) + t.getAnAnnotation() instanceof ReflectiveAccessAnnotation ) or // Enum field annotated with reflective annotation. diff --git a/java/ql/lib/semmle/code/java/deadcode/frameworks/CamelEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/frameworks/CamelEntryPoints.qll index b57d4cbc277..a96565c606e 100644 --- a/java/ql/lib/semmle/code/java/deadcode/frameworks/CamelEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/frameworks/CamelEntryPoints.qll @@ -12,6 +12,6 @@ import semmle.code.java.frameworks.Camel class CamelMessageCallableEntryPoint extends CallableEntryPoint { CamelMessageCallableEntryPoint() { exists(CamelTargetClass camelTargetClass | this = camelTargetClass.getACamelCalledMethod()) or - exists(CamelConsumeMethod consumeMethod | this = consumeMethod) + this instanceof CamelConsumeMethod } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Mockito.qll b/java/ql/lib/semmle/code/java/frameworks/Mockito.qll index e42da4db357..a87050966b2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Mockito.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Mockito.qll @@ -357,7 +357,7 @@ class MockitoSettableField extends Field { MockitoSettableField() { not this.isFinal() and not this.isStatic() and - exists(MockitoMockInjectedClass injectedClass | injectedClass = this.getDeclaringType()) + this.getDeclaringType() instanceof MockitoMockInjectedClass } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll index df3799153e4..17a19c9a228 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll @@ -233,7 +233,7 @@ class SpringBean extends SpringXMLElement { SpringBean getBeanParent() { result.getBeanIdentifier() = this.getBeanParentName() } /** Holds if this bean has a parent bean. */ - predicate hasBeanParent() { exists(SpringBean b | b = this.getBeanParent()) } + predicate hasBeanParent() { exists(this.getBeanParent()) } predicate hasBeanAncestor(SpringBean ancestor) { ancestor = this.getBeanParent() or diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll index 2417002a412..3567f612fc5 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll @@ -58,7 +58,7 @@ class SpringBeanFile extends XMLFile { /** Gets the `default-dependency-check` value for this file. */ string getDefaultDependencyCheck() { - if exists(XMLAttribute a | this.getBeansElement().getAttribute("default-dependency-check") = a) + if exists(this.getBeansElement().getAttribute("default-dependency-check")) then result = this.getBeansElement().getAttributeValue("default-dependency-check") else result = "none" } @@ -70,7 +70,7 @@ class SpringBeanFile extends XMLFile { /** Holds if this file has a `default-destroy-method` value. */ predicate hasDefaultDestroyMethod() { - exists(XMLAttribute a | this.getBeansElement().getAttribute("default-destroy-method") = a) + exists(this.getBeansElement().getAttribute("default-destroy-method")) } /** Gets the `default-init-method` value for this file. */ @@ -80,7 +80,7 @@ class SpringBeanFile extends XMLFile { /** Holds if the file has a `default-destroy-method` value. */ predicate hasDefaultInitMethod() { - exists(XMLAttribute a | this.getBeansElement().getAttribute("default-init-method") = a) + exists(this.getBeansElement().getAttribute("default-init-method")) } /** Holds if `default-lazy-init` is specified to be `true` for this file. */ diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll index 837f7d06100..943285d99a8 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll @@ -18,7 +18,7 @@ class SpringXMLElement extends XMLElement { */ string getAttributeValueWithDefault(string attributeName) { this.hasAttribute(attributeName) and - if exists(XMLAttribute a | a = this.getAttribute(attributeName)) + if exists(this.getAttribute(attributeName)) then result = this.getAttributeValue(attributeName) else result = "default" } diff --git a/java/ql/lib/semmle/code/java/metrics/MetricElement.qll b/java/ql/lib/semmle/code/java/metrics/MetricElement.qll index 3a04fc7f205..086389e143c 100755 --- a/java/ql/lib/semmle/code/java/metrics/MetricElement.qll +++ b/java/ql/lib/semmle/code/java/metrics/MetricElement.qll @@ -43,11 +43,11 @@ class MetricElement extends Element { this.fromSource() and not this.getADependencySrc+() = this and ( - not exists(MetricElement t | t = this.getADependency()) and + not exists(this.getADependency()) and result = 0 or not this.getADependency().fromSource() and - exists(MetricElement e | this.getADependency() = e) and + exists(this.getADependency()) and result = 1 or result = this.getADependency().getALevel() + 1 diff --git a/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll b/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll index fb48d3d6dd7..b818c30edf6 100755 --- a/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll +++ b/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll @@ -18,7 +18,7 @@ class MetricStmt extends Stmt { /** Gets the nested depth of this statement. */ int getNestedDepth() { - not exists(Stmt s | s = this.getParent()) and result = 0 + not this.getParent() instanceof Stmt and result = 0 or exists(MetricStmt s | s = this.getParent() and result = s.getNestedDepth() + 1) } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index 4152cb907ad..d86ab04b441 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -312,7 +312,7 @@ MethodAccess getASafeFlexjsonUseCall() { result.getArgument(0) instanceof NullLiteral or result.getMethod().getParameterType(0) instanceof FlexjsonObjectFactory and - exists(NullLiteral e | e = result.getAnArgument()) + result.getAnArgument() instanceof NullLiteral ) } diff --git a/java/ql/lib/semmle/code/xml/XML.qll b/java/ql/lib/semmle/code/xml/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/java/ql/lib/semmle/code/xml/XML.qll +++ b/java/ql/lib/semmle/code/xml/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/java/ql/src/Architecture/Dependencies/UnusedMavenDependencyBinary.ql b/java/ql/src/Architecture/Dependencies/UnusedMavenDependencyBinary.ql index 65d6250b340..adf79da9ba8 100644 --- a/java/ql/src/Architecture/Dependencies/UnusedMavenDependencyBinary.ql +++ b/java/ql/src/Architecture/Dependencies/UnusedMavenDependencyBinary.ql @@ -23,7 +23,7 @@ where source.getADependency() = d and // There is not a Pom file for the target of this dependency, so we assume that it was resolved by // a binary file in the local maven repository. - not exists(Pom target | target = d.getPom()) and + not exists(d.getPom()) and // In order to accurately identify whether this binary dependency is required, we must have identified // a Maven repository. If we have not found a repository, it's likely that it has a custom path of // which we are unaware, so do not report any problems. diff --git a/java/ql/src/DeadCode/DeadField.ql b/java/ql/src/DeadCode/DeadField.ql index 8981926833a..6a80e13e716 100644 --- a/java/ql/src/DeadCode/DeadField.ql +++ b/java/ql/src/DeadCode/DeadField.ql @@ -16,12 +16,9 @@ import semmle.code.java.deadcode.DeadCode from DeadField f, Element origin, string reason where not f.isInDeadScope() and - if exists(FieldRead read | read = f.getAnAccess()) + if f.getAnAccess() instanceof FieldRead then ( - if - exists(DeadRoot root | - root = getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable()) - ) + if exists(getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable())) then ( origin = getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable()) and reason = " is only read from dead code originating at $@." diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.ql b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.ql index 397a1c349d3..81d18d4b272 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.ql +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.ql @@ -14,5 +14,5 @@ import java import semmle.code.java.frameworks.spring.Spring from SpringBean b -where exists(SpringConstructorArg carg | b.getASpringChild() = carg) +where b.getASpringChild() instanceof SpringConstructorArg select b, "Use setter injection instead of constructor injection." diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.ql b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.ql index cc05679a15b..1d924dc9d6d 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.ql +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.ql @@ -15,12 +15,12 @@ import semmle.code.java.frameworks.spring.Spring class SpringConstructorArgUseShortcut extends SpringConstructorArg { SpringConstructorArgUseShortcut() { not this.hasArgValueString() and - exists(SpringValue val | val = this.getASpringChild()) + this.getASpringChild() instanceof SpringValue } string getMessage() { not this.hasArgValueString() and - exists(SpringValue val | val = this.getASpringChild()) and + this.getASpringChild() instanceof SpringValue and result = "Use the shortcut \"value\" attribute instead of a nested element." } } @@ -28,12 +28,12 @@ class SpringConstructorArgUseShortcut extends SpringConstructorArg { class SpringEntryUseShortcut extends SpringEntry { SpringEntryUseShortcut() { not this.hasValueStringRaw() and - exists(SpringValue val | val = this.getASpringChild()) + this.getASpringChild() instanceof SpringValue } string getMessage() { not this.hasValueStringRaw() and - exists(SpringValue val | val = this.getASpringChild()) and + this.getASpringChild() instanceof SpringValue and result = "Use the shortcut \"value\" attribute instead of a nested element." } } @@ -41,12 +41,12 @@ class SpringEntryUseShortcut extends SpringEntry { class SpringPropertyUseShortcut extends SpringProperty { SpringPropertyUseShortcut() { not this.hasPropertyValueString() and - exists(SpringValue val | val = this.getASpringChild()) + this.getASpringChild() instanceof SpringValue } string getMessage() { not this.hasPropertyValueString() and - exists(SpringValue val | val = this.getASpringChild()) and + this.getASpringChild() instanceof SpringValue and result = "Use the shortcut \"value\" attribute instead of a nested element." } } diff --git a/java/ql/src/Likely Bugs/Cloning/MissingMethodClone.ql b/java/ql/src/Likely Bugs/Cloning/MissingMethodClone.ql index a23a8576f86..6d48a118e29 100644 --- a/java/ql/src/Likely Bugs/Cloning/MissingMethodClone.ql +++ b/java/ql/src/Likely Bugs/Cloning/MissingMethodClone.ql @@ -16,7 +16,7 @@ from Class t, TypeCloneable cloneable where t.hasSupertype+(cloneable) and not t.isAbstract() and - not exists(CloneMethod m | t.getAMethod() = m) and + not t.getAMethod() instanceof CloneMethod and exists(Field f | f.getDeclaringType() = t and not f.isStatic()) and t.fromSource() select t, "No clone method, yet implements Cloneable." diff --git a/java/ql/src/Likely Bugs/Concurrency/WaitOutsideLoop.ql b/java/ql/src/Likely Bugs/Concurrency/WaitOutsideLoop.ql index d136d17dace..644c003a1dc 100644 --- a/java/ql/src/Likely Bugs/Concurrency/WaitOutsideLoop.ql +++ b/java/ql/src/Likely Bugs/Concurrency/WaitOutsideLoop.ql @@ -23,5 +23,5 @@ class WaitMethod extends Method { from MethodAccess ma where ma.getMethod() instanceof WaitMethod and - not exists(LoopStmt s | ma.getEnclosingStmt().getEnclosingStmt*() = s) + not ma.getEnclosingStmt().getEnclosingStmt*() instanceof LoopStmt select ma, "To avoid spurious wake-ups, 'wait' should only be called inside a loop." diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql b/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql index 59388163757..b651d1fcb82 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql @@ -21,5 +21,5 @@ where not f.isStatic() or not f.getType().hasName("long") ) and - exists(TypeSerializable serializable | f.getDeclaringType().getASupertype+() = serializable) + f.getDeclaringType().getASupertype+() instanceof TypeSerializable select f, "serialVersionUID should be final, static, and of type long." diff --git a/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.ql b/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.ql index 5e31cb6ca8c..3a1a41add3d 100644 --- a/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.ql +++ b/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.ql @@ -14,7 +14,7 @@ import java import semmle.code.java.JDKAnnotations -predicate isSerializable(RefType t) { exists(TypeSerializable ts | ts = t.getASupertype*()) } +predicate isSerializable(RefType t) { t.getASupertype*() instanceof TypeSerializable } predicate withinStaticContext(NestedClass c) { c.isStatic() or diff --git a/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql b/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql index 6dd0fa2fcac..33fe1cdb46d 100644 --- a/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql +++ b/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql @@ -16,7 +16,7 @@ predicate nonEmptyArrayLiteralOrNull(Expr e) { exists(ArrayCreationExpr arr | arr = e | // Array initializer expressions such as `{1, 2, 3}`. // Array is empty if the initializer expression is empty. - exists(Expr arrayValue | arrayValue = arr.getInit().getAnInit()) + exists(arr.getInit().getAnInit()) or // Array creation with dimensions (but without initializers). // Empty if the first dimension is 0. diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql b/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql index e4ec03ed956..69175790af7 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql @@ -58,7 +58,7 @@ where not m.getParameterType(_) instanceof HttpServletResponse and // A spring request mapping method which does not have response body annotation applied to it m.getAnAnnotation().getType() instanceof SpringRequestMappingAnnotationType and - not exists(SpringResponseBodyAnnotationType t | t = m.getAnAnnotation().getType()) and + not m.getAnAnnotation().getType() instanceof SpringResponseBodyAnnotationType and // `@RestController` inherits `@ResponseBody` internally so it should be ignored. not m.getDeclaringType() instanceof SpringRestController select m, "This method may be vulnerable to spring view manipulation vulnerabilities" diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll index 9a2a0b9d3d1..a68cfb9fd64 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll @@ -32,9 +32,7 @@ class GetContentIntent extends ClassInstanceExpr { class GetContentIntentConfig extends TaintTracking2::Configuration { GetContentIntentConfig() { this = "GetContentIntentConfig" } - override predicate isSource(DataFlow2::Node src) { - exists(GetContentIntent gi | src.asExpr() = gi) - } + override predicate isSource(DataFlow2::Node src) { src.asExpr() instanceof GetContentIntent } override predicate isSink(DataFlow2::Node sink) { exists(MethodAccess ma | diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql index 3120d25ea11..f917936a33f 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -52,7 +52,7 @@ class KeyGeneratorInitConfiguration extends TaintTracking::Configuration { KeyGeneratorInitConfiguration() { this = "KeyGeneratorInitConfiguration" } override predicate isSource(DataFlow::Node source) { - exists(JavaxCryptoKeyGenerator jcg | jcg = source.asExpr()) + source.asExpr() instanceof JavaxCryptoKeyGenerator } override predicate isSink(DataFlow::Node sink) { @@ -68,7 +68,7 @@ class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration { KeyPairGeneratorInitConfiguration() { this = "KeyPairGeneratorInitConfiguration" } override predicate isSource(DataFlow::Node source) { - exists(JavaSecurityKeyPairGenerator jkg | jkg = source.asExpr()) + source.asExpr() instanceof JavaSecurityKeyPairGenerator } override predicate isSink(DataFlow::Node sink) { diff --git a/javascript/ql/lib/semmle/javascript/XML.qll b/javascript/ql/lib/semmle/javascript/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/javascript/ql/lib/semmle/javascript/XML.qll +++ b/javascript/ql/lib/semmle/javascript/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll index 13ed0c679ae..ff774631b09 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll @@ -433,9 +433,7 @@ private class LibraryAccess extends FileSystemAccess, DataFlow::InvokeNode { or this = DataFlow::moduleMember("node-dir", - any(string s | - s = ["readFiles", "readFilesStream", "files", "promiseFiles", "subdirs", "paths"] - )).getACall() + ["readFiles", "readFilesStream", "files", "promiseFiles", "subdirs", "paths"]).getACall() ) or pathArgument = 0 and diff --git a/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql b/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql index 726c15c0824..43d46d9133b 100644 --- a/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql +++ b/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql @@ -53,9 +53,7 @@ class PostMessageEvent extends DataFlow::SourceNode { * Holds if there is an insufficient method call (i.e indexOf) used to verify `MessageEvent.origin` */ predicate hasOriginInsufficientlyChecked() { - exists(InsufficientOriginChecks insufficientChecks | - this.getAPropertyRead("origin").getAMethodCall*() = insufficientChecks - ) + this.getAPropertyRead("origin").getAMethodCall*() instanceof InsufficientOriginChecks } } diff --git a/javascript/ql/test/testUtilities/ConsistencyChecking.qll b/javascript/ql/test/testUtilities/ConsistencyChecking.qll index f63eb933ff6..9d2f3f8df70 100644 --- a/javascript/ql/test/testUtilities/ConsistencyChecking.qll +++ b/javascript/ql/test/testUtilities/ConsistencyChecking.qll @@ -71,7 +71,7 @@ private DataFlow::Node getASink() { exists(DataFlow::Configuration cfg | cfg.has * Gets all the alerts for consistency consistency checking from a configuration `conf`. */ private DataFlow::Node alerts(Conf conf) { - result = any(ConsistencyConfiguration res | res = conf).getAnAlert() + result = conf.(ConsistencyConfiguration).getAnAlert() or not exists(ConsistencyConfiguration r) and result = getASink() and @@ -131,7 +131,7 @@ private File getATestFile(string conf) { result = any(LineComment comment).getFile() and conf = "" or - result = any(ConsistencyConfiguration res | res = conf).getAFile() + result = conf.(ConsistencyConfiguration).getAFile() } /** diff --git a/python/ql/lib/semmle/python/Comment.qll b/python/ql/lib/semmle/python/Comment.qll index 24810b418ac..012d6c46b41 100644 --- a/python/ql/lib/semmle/python/Comment.qll +++ b/python/ql/lib/semmle/python/Comment.qll @@ -40,7 +40,7 @@ class Comment extends @py_comment { private predicate comment_block_part(Comment start, Comment part, int i) { not exists(Comment prev | prev.getFollowing() = part) and - exists(Comment following | part.getFollowing() = following) and + exists(part.getFollowing()) and start = part and i = 1 or diff --git a/python/ql/lib/semmle/python/Function.qll b/python/ql/lib/semmle/python/Function.qll index acaca8655ad..0397eea605b 100644 --- a/python/ql/lib/semmle/python/Function.qll +++ b/python/ql/lib/semmle/python/Function.qll @@ -18,7 +18,7 @@ class Function extends Function_, Scope, AstNode { override Scope getScope() { result = this.getEnclosingScope() } /** Whether this function is declared in a class */ - predicate isMethod() { exists(Class cls | this.getEnclosingScope() = cls) } + predicate isMethod() { this.getEnclosingScope() instanceof Class } /** Whether this is a special method, that is does its name have the form `__xxx__` (except `__init__`) */ predicate isSpecialMethod() { diff --git a/python/ql/lib/semmle/python/Variables.qll b/python/ql/lib/semmle/python/Variables.qll index 9740d658572..1249fd020ca 100644 --- a/python/ql/lib/semmle/python/Variables.qll +++ b/python/ql/lib/semmle/python/Variables.qll @@ -57,7 +57,7 @@ class LocalVariable extends Variable { override string toString() { result = "Local Variable " + this.getId() } /** Whether this variable is a parameter */ - override predicate isParameter() { exists(Parameter p | this.getAnAccess() = p) } + override predicate isParameter() { this.getAnAccess() instanceof Parameter } /** Holds if this variable is the first parameter of a method. It is not necessarily called "self" */ override predicate isSelf() { @@ -87,7 +87,7 @@ class NameLocalVariable extends LocalVariable { /** A global (module-level) variable */ class GlobalVariable extends Variable { - GlobalVariable() { exists(Module m | m = this.getScope()) } + GlobalVariable() { this.getScope() instanceof Module } override string toString() { result = "Global Variable " + this.getId() } } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll b/python/ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll index c7fd7dcecf3..8dfb86b0950 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/PrintNode.qll @@ -67,6 +67,6 @@ string prettyNodeForInlineTest(DataFlow::Node node) { ) or not exists(node.asExpr()) and - not exists(Expr e | e = node.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr()) and + not exists(node.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr()) and result = node.toString() } diff --git a/python/ql/lib/semmle/python/pointsto/PointsTo.qll b/python/ql/lib/semmle/python/pointsto/PointsTo.qll index 8d58bfa7cdd..1491ee8f7ca 100644 --- a/python/ql/lib/semmle/python/pointsto/PointsTo.qll +++ b/python/ql/lib/semmle/python/pointsto/PointsTo.qll @@ -916,7 +916,7 @@ private module InterModulePointsTo { private predicate exportsSubmodule(Folder folder, string name) { name.regexpMatch("\\p{L}(\\p{L}|\\d|_)*") and ( - exists(Folder child | child = folder.getChildContainer(name)) + folder.getChildContainer(name) instanceof Folder or exists(folder.getFile(name + ".py")) ) diff --git a/python/ql/lib/semmle/python/types/Exceptions.qll b/python/ql/lib/semmle/python/types/Exceptions.qll index 5a04e086779..65fca62c93c 100644 --- a/python/ql/lib/semmle/python/types/Exceptions.qll +++ b/python/ql/lib/semmle/python/types/Exceptions.qll @@ -83,7 +83,7 @@ class RaisingNode extends ControlFlowNode { result = this.innateException_objectapi() ) or - not exists(ExceptFlowNode except | except = this.getAnExceptionalSuccessor()) and + not this.getAnExceptionalSuccessor() instanceof ExceptFlowNode and sequence_or_mapping(this) and result = theLookupErrorType() or @@ -110,7 +110,7 @@ class RaisingNode extends ControlFlowNode { result = this.innateException() ) or - not exists(ExceptFlowNode except | except = this.getAnExceptionalSuccessor()) and + not this.getAnExceptionalSuccessor() instanceof ExceptFlowNode and sequence_or_mapping(this) and result = ClassValue::lookupError() or diff --git a/python/ql/lib/semmle/python/xml/XML.qll b/python/ql/lib/semmle/python/xml/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/python/ql/lib/semmle/python/xml/XML.qll +++ b/python/ql/lib/semmle/python/xml/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/python/ql/src/Statements/MismatchInMultipleAssignment.ql b/python/ql/src/Statements/MismatchInMultipleAssignment.ql index f4ba916cb50..41db397bc73 100644 --- a/python/ql/src/Statements/MismatchInMultipleAssignment.ql +++ b/python/ql/src/Statements/MismatchInMultipleAssignment.ql @@ -46,7 +46,7 @@ predicate mismatched_tuple_rhs(Assign a, int lcount, int rcount, Location loc) { lcount = len(l) and rcount = r.length() and lcount != rcount and - not exists(Starred s | l.getAnItem() = s) + not l.getAnItem() instanceof Starred ) } diff --git a/python/ql/src/Variables/UndefinedExport.ql b/python/ql/src/Variables/UndefinedExport.ql index c53e920d477..c57925cb591 100644 --- a/python/ql/src/Variables/UndefinedExport.ql +++ b/python/ql/src/Variables/UndefinedExport.ql @@ -49,7 +49,7 @@ predicate mutates_globals(ModuleValue m) { or // In Python 3.8, Enum._convert_ is implemented using a metaclass, and our points-to // analysis doesn't handle that well enough. So we need a special case for this - not exists(Value enum_convert | enum_convert = enum_class.attr("_convert")) and + not exists(enum_class.attr("_convert")) and exists(CallNode call | call.getScope() = m.getScope() | call.getFunction().(AttrNode).getObject(["_convert", "_convert_"]).pointsTo() = enum_class ) diff --git a/python/ql/src/Variables/UndefinedGlobal.ql b/python/ql/src/Variables/UndefinedGlobal.ql index bbb48db8fb1..f88f5504df8 100644 --- a/python/ql/src/Variables/UndefinedGlobal.ql +++ b/python/ql/src/Variables/UndefinedGlobal.ql @@ -68,7 +68,7 @@ predicate undefined_use_in_function(Name u) { predicate undefined_use_in_class_or_module(Name u) { exists(GlobalVariable v | u.uses(v)) and - not exists(Function f | u.getScope().getScope*() = f) and + not u.getScope().getScope*() instanceof Function and exists(SsaVariable var | var.getAUse().getNode() = u | var.maybeUndefined()) and not guarded_against_name_error(u) and not exists(ModuleValue m | m.getScope() = u.getEnclosingModule() | m.hasAttribute(u.getId())) and diff --git a/python/ql/src/analysis/Efficiency.ql b/python/ql/src/analysis/Efficiency.ql index 7f08e30502e..ff44fc2c47d 100644 --- a/python/ql/src/analysis/Efficiency.ql +++ b/python/ql/src/analysis/Efficiency.ql @@ -8,7 +8,7 @@ import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext predicate trivial(ControlFlowNode f) { - exists(Parameter p | p = f.getNode()) + f.getNode() instanceof Parameter or f instanceof NameConstantNode or diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll index 19e7b206f82..80bbf2c84b8 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActiveRecord.qll @@ -147,9 +147,7 @@ private Expr sqlFragmentArgument(MethodCall call) { // part of an argument to an SQL executing method private predicate unsafeSqlExpr(Expr sqlFragmentExpr) { // Literals containing an interpolated value - exists(StringInterpolationComponent interpolated | - interpolated = sqlFragmentExpr.(StringlikeLiteral).getComponent(_) - ) + sqlFragmentExpr.(StringlikeLiteral).getComponent(_) instanceof StringInterpolationComponent or // String concatenations sqlFragmentExpr instanceof AddExpr diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll index e68f81d065e..68cab7004f5 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll @@ -39,7 +39,7 @@ class HttpartyRequest extends HTTP::Client::Request::Range { exists(DataFlow::Node r | r = requestNode.getAMethodCall("body") | result = r) or // Otherwise, treat the response as the response body. - not exists(DataFlow::Node r | r = requestNode.getAMethodCall("body")) and + not exists(requestNode.getAMethodCall("body")) and result = requestUse } diff --git a/ruby/ql/src/queries/security/cwe-732/WeakFilePermissions.ql b/ruby/ql/src/queries/security/cwe-732/WeakFilePermissions.ql index d2bc837ac02..0c632df245b 100644 --- a/ruby/ql/src/queries/security/cwe-732/WeakFilePermissions.ql +++ b/ruby/ql/src/queries/security/cwe-732/WeakFilePermissions.ql @@ -48,7 +48,7 @@ class PermissivePermissionsConfig extends DataFlow::Configuration { PermissivePermissionsConfig() { this = "PermissivePermissionsConfig" } override predicate isSource(DataFlow::Node source) { - exists(PermissivePermissionsExpr ppe | source.asExpr().getExpr() = ppe) + source.asExpr().getExpr() instanceof PermissivePermissionsExpr } override predicate isSink(DataFlow::Node sink) { From 8bdbaf4b57482fea2cd8a8d9c1bce7852558a2e3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 20 Jan 2022 09:52:24 +0000 Subject: [PATCH 143/196] C++: Autoformat. --- cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql | 7 ++----- 1 file changed, 2 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 e2f3742cd2d..4c48d58e34e 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -125,13 +125,10 @@ abstract class NetworkSendRecv extends FunctionCall { v.getInitializer().getExpr() instanceof Literal and g = globalValueNumber(v.getAnAccess()) ) - or + or // result of a function call with literal inputs (likely constant) exists(FunctionCall fc | - forex(Expr arg | - arg = fc.getAnArgument() | - arg instanceof Literal - ) and + forex(Expr arg | arg = fc.getAnArgument() | arg instanceof Literal) and g = globalValueNumber(fc) ) // (this is far from exhaustive) From d07997699fd4d7dd312420c25ccddbf21f7856b0 Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Wed, 12 Jan 2022 15:34:17 +0100 Subject: [PATCH 144/196] Introduce generated model for Commons IO --- .../semmle/code/java/frameworks/apache/IO.qll | 214 ++++++++++++++++-- 1 file changed, 201 insertions(+), 13 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll index 3c989fff37f..aec5328be40 100644 --- a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll @@ -3,32 +3,220 @@ import java private import semmle.code.java.dataflow.ExternalFlow -private class CommonsIOSummaryCsv extends SummaryModelCsv { +// manual models that were not generated yet +private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { override predicate row(string row) { row = [ - "org.apache.commons.io;IOUtils;false;buffer;;;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;false;copy;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;copyLarge;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;read;;;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(InputStream,ByteBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(InputStream,int);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;false;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readLines;;;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;false;toBufferedReader;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toByteArray;;;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;false;toCharArray;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toInputStream;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toString;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;write;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;writeChunked;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[0];Argument[2];taint", - "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[1];Argument[2];taint" + "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[0];Argument[2];taint" + ] + } +} + +private class ApacheCommonsIOSinksCsv extends SinkModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io.file;PathFilter;true;accept;(Path,BasicFileAttributes);;Argument[0];create-file", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[0];open-url", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Argument[0];open-url", + "org.apache.commons.io.file;PathUtils;false;newOutputStream;(Path,boolean);;Argument[0];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filter;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filterList;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filterSet;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.input;Tailer$Tailable;true;getRandomAccess;(String);;Argument[-1];create-file", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(URL);;Argument[0];open-url", + "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,Charset);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,CharsetEncoder);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,CharsetEncoder,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,String);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,String,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,Charset);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,CharsetEncoder);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,CharsetEncoder,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,String);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,String,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File);;Argument[0];create-file", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter,boolean,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectoryToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,boolean,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFileToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFileToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyInputStreamToFile;(InputStream,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToDirectory;(Iterable,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToFile;(InputStream,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File);;Argument[0];open-url", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File,int,int);;Argument[0];open-url", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File,int,int);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveDirectoryToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFile;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFile;(File,File,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFileToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;newOutputStream;(File,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;openOutputStream;(File);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;openOutputStream;(File,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;touch;(File);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,Charset);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[]);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],int,int);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],int,int,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,Charset);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;IOUtils;true;copy;(URL,File);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;copy;(URL,File);;Argument[1];create-file", + "org.apache.commons.io;IOUtils;true;copy;(URL,OutputStream);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toByteArray;(URI);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toByteArray;(URL);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI,Charset);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI,String);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL,Charset);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL,String);;Argument[0];open-url", + "org.apache.commons.io;RandomAccessFileMode;false;create;(File);;Argument[0];create-file", + "org.apache.commons.io;RandomAccessFileMode;false;create;(Path);;Argument[0];create-file", + "org.apache.commons.io;RandomAccessFileMode;false;create;(String);;Argument[0];create-file" + ] + } +} + +private class ApacheCommonsIOSourcesCsv extends SourceModelCsv { + override predicate row(string row) { + row = ["org.apache.commons.io;IOUtils;true;toByteArray;(URLConnection);;ReturnValue;remote"] + } +} + +private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io.comparator;CompositeFileComparator;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(String);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URI);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URL);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;getDirList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;getFileList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getCopyOptions;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getSourceDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getTargetDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getByteCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getDirectoryCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getFileCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CountingPathVisitor;true;getPathCounters;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;DirectoryStreamFilter;true;getPathFilter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;getFileFilters;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;NotFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input.buffer;CircularByteBuffer;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.input;BOMInputStream;true;getBOM;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;BOMInputStream;true;getBOMCharsetName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;CharSequenceReader;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;getMessageDigest;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ObservableInputStream;true;getObservers;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;getRandomAccessFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;readLine;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;readLines;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;toString;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getDelayDuration;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getTailable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TimestampedObserver;true;getCloseInstant;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TimestampedObserver;true;getOpenInstant;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TimestampedObserver;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReader;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReader;true;getEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getBomEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeMime;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlGuessEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;getObservers;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getFileFilter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getListeners;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getChildren;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getLastModifiedFileTime;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getParent;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toByteArray;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(Charset);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(String);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.output;AppendableOutputStream;true;getAppendable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AppendableWriter;true;getAppendable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;getData;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.output;StringBuilderWriter;true;getBuilder;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;StringBuilderWriter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;XmlStreamWriter;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;XmlStreamWriter;true;getEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;ByteOrderMark;true;getCharsetName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;ByteOrderMark;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileCleaningTracker;true;getDeleteFailures;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileDeleteStrategy;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOExceptionList;true;getCause;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOExceptionList;true;getCauseList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOExceptionList;true;getCauseList;(Class);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;LineIterator;true;nextLine;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;TaggedIOException;true;getTag;();;Argument[-1];ReturnValue;taint" ] } } From 93f6fde63cf33203a6548973f21fceacfd35f49a Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Thu, 13 Jan 2022 11:23:41 +0100 Subject: [PATCH 145/196] Keep not-yet-covered models --- .../semmle/code/java/frameworks/apache/IO.qll | 445 +++++++++++++++++- 1 file changed, 443 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll index aec5328be40..d4ec8cf999f 100644 --- a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll @@ -3,22 +3,27 @@ import java private import semmle.code.java.dataflow.ExternalFlow -// manual models that were not generated yet +// TODO: manual models that were not generated yet private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { override predicate row(string row) { row = [ "org.apache.commons.io;IOUtils;false;copy;;;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(InputStream,ByteBuffer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;false;toBufferedReader;;;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;false;toCharArray;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[0];Argument[2];taint" + "org.apache.commons.io;IOUtils;false;write;(char[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;false;writeChunked;(char[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[1];Argument[2];taint" ] } } @@ -134,88 +139,524 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { override predicate row(string row) { row = [ + "org.apache.commons.io.comparator;CompositeFileComparator;true;CompositeFileComparator;(Comparator[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.comparator;CompositeFileComparator;true;CompositeFileComparator;(Iterable);;Argument[0];Argument[-1];taint", "org.apache.commons.io.comparator;CompositeFileComparator;true;toString;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(String);;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URI);;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URL);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[2];Argument[-1];taint", "org.apache.commons.io.file;AccumulatorPathVisitor;true;getDirList;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file;AccumulatorPathVisitor;true;getFileList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withBigIntegerCounters;(PathFilter,PathFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withBigIntegerCounters;(PathFilter,PathFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withLongCounters;(PathFilter,PathFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withLongCounters;(PathFilter,PathFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[4];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[5];Argument[-1];taint", "org.apache.commons.io.file;CopyDirectoryVisitor;true;getCopyOptions;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file;CopyDirectoryVisitor;true;getSourceDirectory;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file;CopyDirectoryVisitor;true;getTargetDirectory;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file;Counters$PathCounters;true;getByteCounter;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file;Counters$PathCounters;true;getDirectoryCounter;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.file;Counters$PathCounters;true;getFileCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[2];Argument[-1];taint", "org.apache.commons.io.file;CountingPathVisitor;true;getPathCounters;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;DirectoryStreamFilter;true;DirectoryStreamFilter;(PathFilter);;Argument[0];Argument[-1];taint", "org.apache.commons.io.file;DirectoryStreamFilter;true;getPathFilter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyDirectory;(Path,Path,CopyOption[]);;ArrayElement of Argument[2];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyDirectory;(Path,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;delete;(Path,LinkOption[],DeleteOption[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;deleteDirectory;(Path,LinkOption[],DeleteOption[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;setReadOnly;(Path,boolean,LinkOption[]);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,Path);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,Path,Set,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,String,String[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,URI);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;writeString;(Path,CharSequence,Charset,OpenOption[]);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;AgeFileFilter;(Instant);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;AgeFileFilter;(Instant,boolean);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;AgeFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;addFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;AndFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;addFileFilter;(IOFileFilter);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;ConditionalFileFilter;true;getFileFilters;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;setFileFilters;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;DelegateFileFilter;(FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;DelegateFileFilter;(FilenameFilter);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;DelegateFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileEqualsFileFilter;true;FileEqualsFileFilter;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;and;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;andFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;andFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;asFileFilter;(FileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;asFileFilter;(FilenameFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(String,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(byte[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(byte[],long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeCVSAware;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeDirectoryOnly;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeFileOnly;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeSVNAware;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;nameFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;nameFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;notFileFilter;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;or;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;orFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;orFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;prefixFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;prefixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;toList;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(byte[],long);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;NameFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;NotFileFilter;true;NotFileFilter;(IOFileFilter);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;NotFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;addFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;OrFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;PathEqualsFileFilter;true;PathEqualsFileFilter;(Path);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PathVisitorFileFilter;true;PathVisitorFileFilter;(PathVisitor);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;PrefixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern,Function);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern,Function);;Argument[1];Argument[-1];taint", "org.apache.commons.io.filefilter;RegexFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;SuffixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;WildcardFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;CircularBufferInputStream;true;CircularBufferInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;CircularBufferInputStream;true;CircularBufferInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", "org.apache.commons.io.input.buffer;CircularByteBuffer;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.input.buffer;PeekableInputStream;true;PeekableInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;PeekableInputStream;true;PeekableInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BOMInputStream;true;BOMInputStream;(InputStream,ByteOrderMark[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;BOMInputStream;true;BOMInputStream;(InputStream,boolean,ByteOrderMark[]);;Argument[2];Argument[-1];taint", "org.apache.commons.io.input;BOMInputStream;true;getBOM;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;BOMInputStream;true;getBOMCharsetName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;BoundedInputStream;true;BoundedInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BoundedInputStream;true;BoundedInputStream;(InputStream,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BoundedReader;true;BoundedReader;(Reader,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BrokenInputStream;true;BrokenInputStream;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BrokenReader;true;BrokenReader;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence,int,int);;Argument[0];Argument[-1];taint", "org.apache.commons.io.input;CharSequenceReader;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;CharacterFilterReader;true;CharacterFilterReader;(Reader,IntPredicate);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;CircularInputStream;true;CircularInputStream;(byte[],long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ClassLoaderObjectInputStream;true;ClassLoaderObjectInputStream;(ClassLoader,InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ClassLoaderObjectInputStream;true;ClassLoaderObjectInputStream;(ClassLoader,InputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;CloseShieldInputStream;true;wrap;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;InfiniteCircularInputStream;true;InfiniteCircularInputStream;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream$MessageDigestMaintainingObserver;true;MessageDigestMaintainingObserver;(MessageDigest);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;MessageDigestCalculatingInputStream;(InputStream,MessageDigest);;Argument[1];Argument[-1];taint", "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;getMessageDigest;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ObservableInputStream;true;ObservableInputStream;(InputStream,Observer[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ObservableInputStream;true;add;(Observer);;Argument[0];Argument[-1];taint", "org.apache.commons.io.input;ObservableInputStream;true;getObservers;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;RandomAccessFileInputStream;(RandomAccessFile);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;RandomAccessFileInputStream;(RandomAccessFile,boolean);;Argument[0];Argument[-1];taint", "org.apache.commons.io.input;RandomAccessFileInputStream;true;getRandomAccessFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int,ExecutorService);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int,ExecutorService);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,Charset);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,Charset,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,String,int);;Argument[0];Argument[-1];taint", "org.apache.commons.io.input;ReversedLinesFileReader;true;readLine;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;ReversedLinesFileReader;true;readLines;(int);;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;ReversedLinesFileReader;true;toString;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;SequenceReader;true;SequenceReader;(Iterable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;SequenceReader;true;SequenceReader;(Reader[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(File,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(File,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Path,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Path,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Tailable,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Tailable,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;withBufferSize;(int);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withCharset;(Charset);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer$Builder;true;withReOpen;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withStartThread;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withTailFromEnd;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;create;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[2];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,int);;Argument[1];ReturnValue;taint", "org.apache.commons.io.input;Tailer;true;getDelayDuration;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;Tailer;true;getFile;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;Tailer;true;getTailable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TeeInputStream;true;TeeInputStream;(InputStream,OutputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeInputStream;true;TeeInputStream;(InputStream,OutputStream,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeReader;true;TeeReader;(Reader,Writer);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeReader;true;TeeReader;(Reader,Writer,boolean);;Argument[1];Argument[-1];taint", "org.apache.commons.io.input;TimestampedObserver;true;getCloseInstant;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;TimestampedObserver;true;getOpenInstant;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;TimestampedObserver;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;UncheckedBufferedReader;(Reader);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;UncheckedBufferedReader;(Reader,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;on;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;UncheckedFilterInputStream;true;on;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;UnixLineEndingInputStream;true;UnixLineEndingInputStream;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[],int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;WindowsLineEndingInputStream;true;WindowsLineEndingInputStream;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(URLConnection,String);;Argument[1];Argument[-1];taint", "org.apache.commons.io.input;XmlStreamReader;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;XmlStreamReader;true;getEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[4];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[5];Argument[-1];taint", "org.apache.commons.io.input;XmlStreamReaderException;true;getBomEncoding;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeEncoding;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeMime;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlEncoding;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlGuessEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;FileAlterationMonitor;(long,Collection);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;FileAlterationMonitor;(long,FileAlterationObserver[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;addObserver;(FileAlterationObserver);;Argument[0];Argument[-1];taint", "org.apache.commons.io.monitor;FileAlterationMonitor;false;getObservers;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;setThreadFactory;(ThreadFactory);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter,IOCase);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter,IOCase);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;addListener;(FileAlterationListener);;Argument[0];Argument[-1];taint", "org.apache.commons.io.monitor;FileAlterationObserver;true;getDirectory;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileAlterationObserver;true;getFileFilter;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileAlterationObserver;true;getListeners;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileAlterationObserver;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(FileEntry,File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(FileEntry,File);;Argument[1];Argument[-1];taint", "org.apache.commons.io.monitor;FileEntry;true;getChildren;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileEntry;true;getFile;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileEntry;true;getLastModifiedFileTime;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileEntry;true;getName;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileEntry;true;getParent;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;setChildren;(FileEntry[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;setLastModified;(FileTime);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;setName;(String);;Argument[0];Argument[-1];taint", "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toByteArray;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(Charset);;Argument[-1];ReturnValue;taint", "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(String);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;write;(InputStream);;Argument[0];Argument[-1];taint", "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.output;AppendableOutputStream;true;AppendableOutputStream;(Appendable);;Argument[0];Argument[-1];taint", "org.apache.commons.io.output;AppendableOutputStream;true;getAppendable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AppendableWriter;true;AppendableWriter;(Appendable);;Argument[0];Argument[-1];taint", "org.apache.commons.io.output;AppendableWriter;true;getAppendable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;BrokenOutputStream;true;BrokenOutputStream;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;BrokenWriter;true;BrokenWriter;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ChunkedOutputStream;true;ChunkedOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ChunkedOutputStream;true;ChunkedOutputStream;(OutputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;CloseShieldOutputStream;true;CloseShieldOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;CloseShieldOutputStream;true;wrap;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;CountingOutputStream;true;CountingOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,File);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[4];Argument[-1];taint", "org.apache.commons.io.output;DeferredFileOutputStream;true;getData;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.output;DeferredFileOutputStream;true;getFile;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,Charset,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,String,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(String,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;ProxyCollectionWriter;true;ProxyCollectionWriter;(Collection);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ProxyCollectionWriter;true;ProxyCollectionWriter;(Writer[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ProxyOutputStream;true;ProxyOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;StringBuilderWriter;true;StringBuilderWriter;(StringBuilder);;Argument[0];Argument[-1];taint", "org.apache.commons.io.output;StringBuilderWriter;true;getBuilder;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.output;StringBuilderWriter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;TaggedOutputStream;true;TaggedOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeOutputStream;true;TeeOutputStream;(OutputStream,OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeOutputStream;true;TeeOutputStream;(OutputStream,OutputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;TeeWriter;true;TeeWriter;(Collection);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeWriter;true;TeeWriter;(Writer[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ThresholdingOutputStream;true;ThresholdingOutputStream;(int,IOConsumer,IOFunction);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;ThresholdingOutputStream;true;ThresholdingOutputStream;(int,IOConsumer,IOFunction);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;UncheckedAppendable;true;on;(Appendable);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;UncheckedFilterOutputStream;true;UncheckedFilterOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;UncheckedFilterOutputStream;true;on;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,Charset);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,Charset,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder,int,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,String,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream,String);;Argument[1];Argument[-1];taint", "org.apache.commons.io.output;XmlStreamWriter;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.output;XmlStreamWriter;true;getEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;ValidatingObjectInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Class[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Class[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;ByteOrderMark;true;ByteOrderMark;(String,int[]);;Argument[0];Argument[-1];taint", "org.apache.commons.io;ByteOrderMark;true;getCharsetName;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io;ByteOrderMark;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(File,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(String,File,int);;Argument[1];Argument[-1];taint", "org.apache.commons.io;DirectoryWalker$CancelException;true;getFile;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io;FileCleaningTracker;true;getDeleteFailures;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(File,Object,FileDeleteStrategy);;Argument[2];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object,FileDeleteStrategy);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object,FileDeleteStrategy);;Argument[2];Argument[-1];taint", "org.apache.commons.io;FileDeleteStrategy;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileSystem;false;toLegalFileName;(String,char);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;checksum;(File,Checksum);;Argument[1];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;convertFileCollectionToFileArray;(Collection);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;delete;(File);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(File,String[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(File,String[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;toURLs;(File[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;concat;(String,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;concat;(String,String);;Argument[1];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getBaseName;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getExtension;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getFullPath;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getFullPathNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getName;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPath;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPathNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPrefix;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalize;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalize;(String,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalizeNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalizeNoEndSeparator;(String,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;removeExtension;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;HexDump;true;dump;(byte[],long,OutputStream,int);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOExceptionList;true;IOExceptionList;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;IOExceptionList;true;IOExceptionList;(String,List);;Argument[1];Argument[-1];taint", "org.apache.commons.io;IOExceptionList;true;getCause;(int);;Argument[-1];ReturnValue;taint", "org.apache.commons.io;IOExceptionList;true;getCauseList;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io;IOExceptionList;true;getCauseList;(Class);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(OutputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Reader,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Writer);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Writer,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[4];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[4];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[4];taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(Reader,char[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(byte[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(byte[],String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Element of Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,Charset);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Element of Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writer;(Appendable);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;LineIterator;true;LineIterator;(Reader);;Argument[0];Argument[-1];taint", "org.apache.commons.io;LineIterator;true;nextLine;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;TaggedIOException;true;TaggedIOException;(IOException,Serializable);;Argument[1];Argument[-1];taint", "org.apache.commons.io;TaggedIOException;true;getTag;();;Argument[-1];ReturnValue;taint" ] } From b20b3ab4807843d50196e450c6f1b0e62e8d31ea Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Fri, 14 Jan 2022 11:25:42 +0100 Subject: [PATCH 146/196] Regenrate model to replace manual models --- .../semmle/code/java/frameworks/apache/IO.qll | 50 +++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll index d4ec8cf999f..af2426a3e78 100644 --- a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll @@ -8,22 +8,10 @@ private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { override predicate row(string row) { row = [ - "org.apache.commons.io;IOUtils;false;copy;;;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(InputStream,ByteBuffer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;false;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toBufferedReader;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toCharArray;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;write;(char[],Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;writeChunked;(char[],Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[0];Argument[2];taint", - "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[1];Argument[2];taint" + "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint" ] } } @@ -131,7 +119,7 @@ private class ApacheCommonsIOSinksCsv extends SinkModelCsv { private class ApacheCommonsIOSourcesCsv extends SourceModelCsv { override predicate row(string row) { - row = ["org.apache.commons.io;IOUtils;true;toByteArray;(URLConnection);;ReturnValue;remote"] + row = ["org.apache.commons.io;IOUtils;true;toByteArray;(URL);;ReturnValue;remote"] } } @@ -241,7 +229,10 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String);;Argument[0];ReturnValue;taint", "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", "org.apache.commons.io.filefilter;FileFilterUtils;true;toList;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[-1];ReturnValue;taint", "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;negate;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[-1];ReturnValue;taint", "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[0];ReturnValue;taint", "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String);;Argument[0];Argument[-1];taint", "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String,long);;Argument[0];Argument[-1];taint", @@ -456,6 +447,7 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io.monitor;FileEntry;true;getLastModifiedFileTime;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileEntry;true;getName;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileEntry;true;getParent;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[-1];ReturnValue;taint", "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[0];ReturnValue;taint", "org.apache.commons.io.monitor;FileEntry;true;setChildren;(FileEntry[]);;Argument[0];Argument[-1];taint", "org.apache.commons.io.monitor;FileEntry;true;setLastModified;(FileTime);;Argument[0];Argument[-1];taint", @@ -548,6 +540,8 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;ByteOrderMark;true;getCharsetName;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io;ByteOrderMark;true;toString;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io;CopyUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(String,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;CopyUtils;true;copy;(byte[],OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(File,int);;Argument[0];Argument[-1];taint", "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(String,File,int);;Argument[1];Argument[-1];taint", @@ -595,30 +589,44 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;buffer;(Reader,int);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;buffer;(Writer);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;buffer;(Writer,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,OutputStream,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,Charset);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[2];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(Reader,OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(Reader,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[2];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[4];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[4];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[4];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[4];Argument[1];taint", "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,Charset);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,String);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;lineIterator;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(Reader,char[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;read;(Reader,char[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readFully;(InputStream,int);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readLines;(InputStream);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;readLines;(InputStream,Charset);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;readLines;(InputStream,String);;Argument[0];ReturnValue;taint", @@ -645,14 +653,28 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;toString;(Reader);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toString;(byte[]);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toString;(byte[],String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeChunked;(char[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Argument[1];Argument[2];taint", "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Element of Argument[0];Argument[2];taint", "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,Charset);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Argument[1];Argument[2];taint", "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Element of Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[1];Argument[2];taint", "org.apache.commons.io;IOUtils;true;writer;(Appendable);;Argument[0];ReturnValue;taint", "org.apache.commons.io;LineIterator;true;LineIterator;(Reader);;Argument[0];Argument[-1];taint", "org.apache.commons.io;LineIterator;true;nextLine;();;Argument[-1];ReturnValue;taint", From 857c2778a6aba554893e5448f378e711a720f376 Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Fri, 14 Jan 2022 15:46:36 +0100 Subject: [PATCH 147/196] Added missing model for ReadableByteChannel This reveals more models for commons io --- .../semmle/code/java/frameworks/apache/IO.qll | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll index af2426a3e78..916bbce1e80 100644 --- a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll @@ -7,12 +7,7 @@ private import semmle.code.java.dataflow.ExternalFlow private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(InputStream,ByteBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint" - ] + ["org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint"] } } @@ -540,6 +535,8 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;ByteOrderMark;true;getCharsetName;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io;ByteOrderMark;true;toString;();;Argument[-1];ReturnValue;taint", "org.apache.commons.io;CopyUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", "org.apache.commons.io;CopyUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;CopyUtils;true;copy;(String,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;CopyUtils;true;copy;(byte[],OutputStream);;Argument[0];Argument[1];taint", @@ -598,8 +595,6 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[2];taint", "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[2];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(Reader,OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(Reader,OutputStream,String);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[1];taint", @@ -609,9 +604,11 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[4];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[4];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[2];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[4];taint", "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[4];Argument[1];taint", @@ -620,11 +617,13 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;lineIterator;(Reader);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;read;(Reader,char[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;read;(Reader,char[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readFully;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;readLines;(InputStream);;Argument[0];ReturnValue;taint", @@ -636,11 +635,8 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,int);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,long);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,Charset);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toByteArray;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,String);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,Charset);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,String);;Argument[0];ReturnValue;taint", @@ -653,7 +649,10 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;toString;(Reader);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toString;(byte[]);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toString;(byte[],String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(String,OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,Charset);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,String);;Argument[0];Argument[1];taint", @@ -662,7 +661,9 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream,String);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(StringBuffer,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,String);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,Charset);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,String);;Argument[0];Argument[1];taint", @@ -670,10 +671,8 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;writeChunked;(char[],Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Argument[1];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Element of Argument[0];Argument[2];taint", "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,Charset);;Argument[1];Argument[2];taint", "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Argument[1];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Element of Argument[0];Argument[2];taint", "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[1];Argument[2];taint", "org.apache.commons.io;IOUtils;true;writer;(Appendable);;Argument[0];ReturnValue;taint", "org.apache.commons.io;LineIterator;true;LineIterator;(Reader);;Argument[0];Argument[-1];taint", From 4cac35adad40eab93e305cfbcda18159f971ae6f Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Mon, 17 Jan 2022 13:09:13 +0100 Subject: [PATCH 148/196] Regnerate model to capture char[] APIs --- .../code/java/dataflow/ExternalFlow.qll | 1 + .../semmle/code/java/frameworks/apache/IO.qll | 30 +++++++++---------- .../code/java/frameworks/apache/IOCustom.qll | 17 +++++++++++ 3 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/frameworks/apache/IOCustom.qll diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index 839d1fa69e2..c3090e7d2e9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -86,6 +86,7 @@ private module Frameworks { private import semmle.code.java.frameworks.ApacheHttp private import semmle.code.java.frameworks.apache.Collections private import semmle.code.java.frameworks.apache.IO + private import semmle.code.java.frameworks.apache.IOCustom private import semmle.code.java.frameworks.apache.Lang private import semmle.code.java.frameworks.Flexjson private import semmle.code.java.frameworks.guava.Guava diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll index 916bbce1e80..87bdcf12ce6 100644 --- a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll @@ -1,17 +1,9 @@ -/** Definitions related to the Apache Commons IO library. */ +/** Definitions of taint steps in the IO framework */ import java private import semmle.code.java.dataflow.ExternalFlow -// TODO: manual models that were not generated yet -private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { - override predicate row(string row) { - row = - ["org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint"] - } -} - -private class ApacheCommonsIOSinksCsv extends SinkModelCsv { +private class IOSinksCsv extends SinkModelCsv { override predicate row(string row) { row = [ @@ -112,13 +104,17 @@ private class ApacheCommonsIOSinksCsv extends SinkModelCsv { } } -private class ApacheCommonsIOSourcesCsv extends SourceModelCsv { +private class IOSourcesCsv extends SourceModelCsv { override predicate row(string row) { - row = ["org.apache.commons.io;IOUtils;true;toByteArray;(URL);;ReturnValue;remote"] + row = + [ + "org.apache.commons.io;IOUtils;true;resourceToByteArray;(String,ClassLoader);;ReturnValue;remote", + "org.apache.commons.io;IOUtils;true;toByteArray;(URI);;ReturnValue;remote" + ] } } -private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { +private class IOSummaryCsv extends SummaryModelCsv { override predicate row(string row) { row = [ @@ -540,6 +536,8 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;CopyUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;CopyUtils;true;copy;(String,Writer);;Argument[0];Argument[1];taint", "org.apache.commons.io;CopyUtils;true;copy;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],Writer,String);;Argument[0];Argument[1];taint", "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(File,int);;Argument[0];Argument[-1];taint", "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(String,File,int);;Argument[1];Argument[-1];taint", "org.apache.commons.io;DirectoryWalker$CancelException;true;getFile;();;Argument[-1];ReturnValue;taint", @@ -634,9 +632,11 @@ private class ApacheCommonsIOSummaryCsv extends SummaryModelCsv { "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader,int);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,int);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,long);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toByteArray;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(Reader);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,Charset);;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,String);;Argument[0];ReturnValue;taint", diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IOCustom.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IOCustom.qll new file mode 100644 index 00000000000..89af5962a0e --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IOCustom.qll @@ -0,0 +1,17 @@ +/** Custom definitions related to the Apache Commons IO library. */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +// TODO: manual models that were not generated yet +private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint", + ] + } +} From 8217873bae16fbc6b90f46345422a5614ccd75b8 Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Thu, 20 Jan 2022 11:02:53 +0100 Subject: [PATCH 149/196] Align files with new naming pattern --- .../code/java/dataflow/ExternalFlow.qll | 1 - .../semmle/code/java/frameworks/apache/IO.qll | 682 +---------------- .../code/java/frameworks/apache/IOCustom.qll | 17 - .../java/frameworks/apache/IOGenerated.qll | 684 ++++++++++++++++++ 4 files changed, 692 insertions(+), 692 deletions(-) delete mode 100644 java/ql/lib/semmle/code/java/frameworks/apache/IOCustom.qll create mode 100644 java/ql/lib/semmle/code/java/frameworks/apache/IOGenerated.qll diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index c3090e7d2e9..839d1fa69e2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -86,7 +86,6 @@ private module Frameworks { private import semmle.code.java.frameworks.ApacheHttp private import semmle.code.java.frameworks.apache.Collections private import semmle.code.java.frameworks.apache.IO - private import semmle.code.java.frameworks.apache.IOCustom private import semmle.code.java.frameworks.apache.Lang private import semmle.code.java.frameworks.Flexjson private import semmle.code.java.frameworks.guava.Guava diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll index 87bdcf12ce6..2c3d79f2798 100644 --- a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll @@ -1,684 +1,18 @@ -/** Definitions of taint steps in the IO framework */ +/** Custom definitions related to the Apache Commons IO library. */ import java +import IOGenerated private import semmle.code.java.dataflow.ExternalFlow -private class IOSinksCsv extends SinkModelCsv { +// TODO: manual models that were not generated yet +private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { override predicate row(string row) { row = [ - "org.apache.commons.io.file;PathFilter;true;accept;(Path,BasicFileAttributes);;Argument[0];create-file", - "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[0];open-url", - "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[1];create-file", - "org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Argument[0];open-url", - "org.apache.commons.io.file;PathUtils;false;newOutputStream;(Path,boolean);;Argument[0];create-file", - "org.apache.commons.io.filefilter;FileFilterUtils;true;filter;(IOFileFilter,File[]);;Argument[1];create-file", - "org.apache.commons.io.filefilter;FileFilterUtils;true;filterList;(IOFileFilter,File[]);;Argument[1];create-file", - "org.apache.commons.io.filefilter;FileFilterUtils;true;filterSet;(IOFileFilter,File[]);;Argument[1];create-file", - "org.apache.commons.io.input;Tailer$Tailable;true;getRandomAccess;(String);;Argument[-1];create-file", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(URL);;Argument[0];open-url", - "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,Charset);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,Charset,boolean);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,CharsetEncoder);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,CharsetEncoder,boolean);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,String);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,String,boolean);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,Charset);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,Charset,boolean);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,CharsetEncoder);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,CharsetEncoder,boolean);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,String);;Argument[0];create-file", - "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,String,boolean);;Argument[0];create-file", - "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File);;Argument[0];create-file", - "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File,String);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter,boolean);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter,boolean,CopyOption[]);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,boolean);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyDirectoryToDirectory;(File,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyFile;(File,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyFile;(File,File,CopyOption[]);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyFile;(File,File,boolean);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyFile;(File,File,boolean,CopyOption[]);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyFileToDirectory;(File,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyFileToDirectory;(File,File,boolean);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyInputStreamToFile;(InputStream,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyToDirectory;(File,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyToDirectory;(Iterable,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyToFile;(InputStream,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File);;Argument[0];open-url", - "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File,int,int);;Argument[0];open-url", - "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File,int,int);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;moveDirectory;(File,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;moveDirectoryToDirectory;(File,File,boolean);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;moveFile;(File,File);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;moveFile;(File,File,CopyOption[]);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;moveFileToDirectory;(File,File,boolean);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;moveToDirectory;(File,File,boolean);;Argument[1];create-file", - "org.apache.commons.io;FileUtils;true;newOutputStream;(File,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;openOutputStream;(File);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;openOutputStream;(File,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;touch;(File);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;write;(File,CharSequence);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,Charset);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,Charset,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,String);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,String,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[]);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],int,int);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],int,int,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,String);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,String,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,String);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,String,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,Charset);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,Charset,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,String);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,String,boolean);;Argument[0];create-file", - "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,boolean);;Argument[0];create-file", - "org.apache.commons.io;IOUtils;true;copy;(URL,File);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;copy;(URL,File);;Argument[1];create-file", - "org.apache.commons.io;IOUtils;true;copy;(URL,OutputStream);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;toByteArray;(URI);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;toByteArray;(URL);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;toString;(URI);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;toString;(URI,Charset);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;toString;(URI,String);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;toString;(URL);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;toString;(URL,Charset);;Argument[0];open-url", - "org.apache.commons.io;IOUtils;true;toString;(URL,String);;Argument[0];open-url", - "org.apache.commons.io;RandomAccessFileMode;false;create;(File);;Argument[0];create-file", - "org.apache.commons.io;RandomAccessFileMode;false;create;(Path);;Argument[0];create-file", - "org.apache.commons.io;RandomAccessFileMode;false;create;(String);;Argument[0];create-file" - ] - } -} - -private class IOSourcesCsv extends SourceModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.io;IOUtils;true;resourceToByteArray;(String,ClassLoader);;ReturnValue;remote", - "org.apache.commons.io;IOUtils;true;toByteArray;(URI);;ReturnValue;remote" - ] - } -} - -private class IOSummaryCsv extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.io.comparator;CompositeFileComparator;true;CompositeFileComparator;(Comparator[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.comparator;CompositeFileComparator;true;CompositeFileComparator;(Iterable);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.comparator;CompositeFileComparator;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(String);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URI);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URL);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;getDirList;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;getFileList;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;withBigIntegerCounters;(PathFilter,PathFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;withBigIntegerCounters;(PathFilter,PathFilter);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;withLongCounters;(PathFilter,PathFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.file;AccumulatorPathVisitor;true;withLongCounters;(PathFilter,PathFilter);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,String[]);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[4];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[5];Argument[-1];taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;getCopyOptions;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;getSourceDirectory;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;CopyDirectoryVisitor;true;getTargetDirectory;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;Counters$PathCounters;true;getByteCounter;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;Counters$PathCounters;true;getDirectoryCounter;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;Counters$PathCounters;true;getFileCounter;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.file;CountingPathVisitor;true;getPathCounters;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,String[]);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.file;DirectoryStreamFilter;true;DirectoryStreamFilter;(PathFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.file;DirectoryStreamFilter;true;getPathFilter;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;copyDirectory;(Path,Path,CopyOption[]);;ArrayElement of Argument[2];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;copyDirectory;(Path,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;delete;(Path,LinkOption[],DeleteOption[]);;ArrayElement of Argument[1];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;deleteDirectory;(Path,LinkOption[],DeleteOption[]);;ArrayElement of Argument[1];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;setReadOnly;(Path,boolean,LinkOption[]);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,Path);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,Path,Set,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,String,String[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,URI);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.file;PathUtils;false;writeString;(Path,CharSequence,Charset,OpenOption[]);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;AgeFileFilter;true;AgeFileFilter;(Instant);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;AgeFileFilter;true;AgeFileFilter;(Instant,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;AgeFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;AndFileFilter;true;addFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;AndFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;ConditionalFileFilter;true;addFileFilter;(IOFileFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;ConditionalFileFilter;true;getFileFilters;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;ConditionalFileFilter;true;setFileFilters;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;DelegateFileFilter;true;DelegateFileFilter;(FileFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;DelegateFileFilter;true;DelegateFileFilter;(FilenameFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;DelegateFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileEqualsFileFilter;true;FileEqualsFileFilter;(File);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;and;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;andFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;andFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;asFileFilter;(FileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;asFileFilter;(FilenameFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(String,long);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(byte[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(byte[],long);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;makeCVSAware;(IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;makeDirectoryOnly;(IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;makeFileOnly;(IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;makeSVNAware;(IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;nameFileFilter;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;nameFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;notFileFilter;(IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;or;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;orFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;orFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;prefixFileFilter;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;prefixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;FileFilterUtils;true;toList;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;IOFileFilter;true;negate;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String,long);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(byte[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(byte[],long);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;NameFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;NotFileFilter;true;NotFileFilter;(IOFileFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;NotFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;OrFileFilter;true;addFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;OrFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;PathEqualsFileFilter;true;PathEqualsFileFilter;(Path);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;PathVisitorFileFilter;true;PathVisitorFileFilter;(PathVisitor);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;PrefixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern,Function);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern,Function);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.filefilter;RegexFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;SuffixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;WildcardFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input.buffer;CircularBufferInputStream;true;CircularBufferInputStream;(InputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input.buffer;CircularBufferInputStream;true;CircularBufferInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input.buffer;CircularByteBuffer;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint", - "org.apache.commons.io.input.buffer;PeekableInputStream;true;PeekableInputStream;(InputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input.buffer;PeekableInputStream;true;PeekableInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;BOMInputStream;true;BOMInputStream;(InputStream,ByteOrderMark[]);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;BOMInputStream;true;BOMInputStream;(InputStream,boolean,ByteOrderMark[]);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.input;BOMInputStream;true;getBOM;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;BOMInputStream;true;getBOMCharsetName;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;BoundedInputStream;true;BoundedInputStream;(InputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;BoundedInputStream;true;BoundedInputStream;(InputStream,long);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;BoundedReader;true;BoundedReader;(Reader,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;BrokenInputStream;true;BrokenInputStream;(Supplier);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;BrokenReader;true;BrokenReader;(Supplier);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;CharSequenceReader;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;CharacterFilterReader;true;CharacterFilterReader;(Reader,IntPredicate);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;CircularInputStream;true;CircularInputStream;(byte[],long);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ClassLoaderObjectInputStream;true;ClassLoaderObjectInputStream;(ClassLoader,InputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ClassLoaderObjectInputStream;true;ClassLoaderObjectInputStream;(ClassLoader,InputStream);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;CloseShieldInputStream;true;wrap;(InputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;InfiniteCircularInputStream;true;InfiniteCircularInputStream;(byte[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;MessageDigestCalculatingInputStream$MessageDigestMaintainingObserver;true;MessageDigestMaintainingObserver;(MessageDigest);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;MessageDigestCalculatingInputStream;(InputStream,MessageDigest);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;getMessageDigest;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;ObservableInputStream;true;ObservableInputStream;(InputStream,Observer[]);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;ObservableInputStream;true;add;(Observer);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ObservableInputStream;true;getObservers;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;RandomAccessFileInputStream;true;RandomAccessFileInputStream;(RandomAccessFile);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;RandomAccessFileInputStream;true;RandomAccessFileInputStream;(RandomAccessFile,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;RandomAccessFileInputStream;true;getRandomAccessFile;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int,ExecutorService);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int,ExecutorService);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,Charset);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,Charset,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder,int);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,String,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;ReversedLinesFileReader;true;readLine;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;ReversedLinesFileReader;true;readLines;(int);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;ReversedLinesFileReader;true;toString;(int);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;SequenceReader;true;SequenceReader;(Iterable);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;SequenceReader;true;SequenceReader;(Reader[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer$Builder;true;Builder;(File,TailerListener);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer$Builder;true;Builder;(File,TailerListener);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Path,TailerListener);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Path,TailerListener);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Tailable,TailerListener);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Tailable,TailerListener);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer$Builder;true;withBufferSize;(int);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.input;Tailer$Builder;true;withCharset;(Charset);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;Tailer$Builder;true;withReOpen;(boolean);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.input;Tailer$Builder;true;withStartThread;(boolean);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.input;Tailer$Builder;true;withTailFromEnd;(boolean);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean,int);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,int);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;Tailer;true;create;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[2];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean,int);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,int);;Argument[1];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;getDelayDuration;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;getFile;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;Tailer;true;getTailable;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;TeeInputStream;true;TeeInputStream;(InputStream,OutputStream);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;TeeInputStream;true;TeeInputStream;(InputStream,OutputStream,boolean);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;TeeReader;true;TeeReader;(Reader,Writer);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;TeeReader;true;TeeReader;(Reader,Writer,boolean);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;TimestampedObserver;true;getCloseInstant;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;TimestampedObserver;true;getOpenInstant;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;TimestampedObserver;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;UncheckedBufferedReader;true;UncheckedBufferedReader;(Reader);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;UncheckedBufferedReader;true;UncheckedBufferedReader;(Reader,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;UncheckedBufferedReader;true;on;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;UncheckedFilterInputStream;true;on;(InputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.input;UnixLineEndingInputStream;true;UnixLineEndingInputStream;(InputStream,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[],int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[],int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;WindowsLineEndingInputStream;true;WindowsLineEndingInputStream;(InputStream,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean,String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean,String);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean,String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean,String);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(URLConnection,String);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReader;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;XmlStreamReader;true;getEncoding;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[4];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[5];Argument[-1];taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;getBomEncoding;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeEncoding;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeMime;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlEncoding;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlGuessEncoding;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileAlterationMonitor;false;FileAlterationMonitor;(long,Collection);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationMonitor;false;FileAlterationMonitor;(long,FileAlterationObserver[]);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationMonitor;false;addObserver;(FileAlterationObserver);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationMonitor;false;getObservers;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileAlterationMonitor;false;setThreadFactory;(ThreadFactory);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter,IOCase);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter,IOCase);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter,IOCase);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;addListener;(FileAlterationListener);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;getDirectory;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;getFileFilter;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;getListeners;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileAlterationObserver;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(File);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(FileEntry,File);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(FileEntry,File);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.monitor;FileEntry;true;getChildren;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileEntry;true;getFile;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileEntry;true;getLastModifiedFileTime;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileEntry;true;getName;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileEntry;true;getParent;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.monitor;FileEntry;true;setChildren;(FileEntry[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileEntry;true;setLastModified;(FileTime);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.monitor;FileEntry;true;setName;(String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toByteArray;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(Charset);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(String);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;write;(InputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", - "org.apache.commons.io.output;AppendableOutputStream;true;AppendableOutputStream;(Appendable);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;AppendableOutputStream;true;getAppendable;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;AppendableWriter;true;AppendableWriter;(Appendable);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;AppendableWriter;true;getAppendable;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;BrokenOutputStream;true;BrokenOutputStream;(Supplier);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;BrokenWriter;true;BrokenWriter;(Supplier);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;ChunkedOutputStream;true;ChunkedOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;ChunkedOutputStream;true;ChunkedOutputStream;(OutputStream,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;CloseShieldOutputStream;true;CloseShieldOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;CloseShieldOutputStream;true;wrap;(OutputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.output;CountingOutputStream;true;CountingOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,File);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,File);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[4];Argument[-1];taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;getData;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;getFile;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", - "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,Charset,boolean,String);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,String,boolean,String);;Argument[3];Argument[-1];taint", - "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,boolean,String);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(String,boolean,String);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.output;ProxyCollectionWriter;true;ProxyCollectionWriter;(Collection);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;ProxyCollectionWriter;true;ProxyCollectionWriter;(Writer[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;ProxyOutputStream;true;ProxyOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;StringBuilderWriter;true;StringBuilderWriter;(StringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;StringBuilderWriter;true;getBuilder;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;StringBuilderWriter;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;TaggedOutputStream;true;TaggedOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;TeeOutputStream;true;TeeOutputStream;(OutputStream,OutputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;TeeOutputStream;true;TeeOutputStream;(OutputStream,OutputStream);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.output;TeeWriter;true;TeeWriter;(Collection);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;TeeWriter;true;TeeWriter;(Writer[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;ThresholdingOutputStream;true;ThresholdingOutputStream;(int,IOConsumer,IOFunction);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.output;ThresholdingOutputStream;true;ThresholdingOutputStream;(int,IOConsumer,IOFunction);;Argument[2];Argument[-1];taint", - "org.apache.commons.io.output;UncheckedAppendable;true;on;(Appendable);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.output;UncheckedFilterOutputStream;true;UncheckedFilterOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;UncheckedFilterOutputStream;true;on;(OutputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,Charset);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,Charset,int,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder,int,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder,int,boolean);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,String,int,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File,String);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream,String);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream,String);;Argument[1];Argument[-1];taint", - "org.apache.commons.io.output;XmlStreamWriter;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.output;XmlStreamWriter;true;getEncoding;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;ValidatingObjectInputStream;(InputStream);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Class[]);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Class[]);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[0];ReturnValue;taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;Argument[-1];ReturnValue;value", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.io;ByteOrderMark;true;ByteOrderMark;(String,int[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.io;ByteOrderMark;true;getCharsetName;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;ByteOrderMark;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;CopyUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;CopyUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;CopyUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", - "org.apache.commons.io;CopyUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;CopyUtils;true;copy;(String,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;CopyUtils;true;copy;(byte[],OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;CopyUtils;true;copy;(byte[],Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;CopyUtils;true;copy;(byte[],Writer,String);;Argument[0];Argument[1];taint", - "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(File,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(String,File,int);;Argument[1];Argument[-1];taint", - "org.apache.commons.io;DirectoryWalker$CancelException;true;getFile;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;FileCleaningTracker;true;getDeleteFailures;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;FileCleaningTracker;true;track;(File,Object,FileDeleteStrategy);;Argument[2];Argument[-1];taint", - "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object);;Argument[0];Argument[-1];taint", - "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object,FileDeleteStrategy);;Argument[0];Argument[-1];taint", - "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object,FileDeleteStrategy);;Argument[2];Argument[-1];taint", - "org.apache.commons.io;FileDeleteStrategy;true;toString;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;FileSystem;false;toLegalFileName;(String,char);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FileUtils;true;checksum;(File,Checksum);;Argument[1];ReturnValue;taint", - "org.apache.commons.io;FileUtils;true;convertFileCollectionToFileArray;(Collection);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.io;FileUtils;true;delete;(File);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FileUtils;true;getFile;(File,String[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FileUtils;true;getFile;(File,String[]);;ArrayElement of Argument[1];ReturnValue;taint", - "org.apache.commons.io;FileUtils;true;getFile;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.io;FileUtils;true;toURLs;(File[]);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;concat;(String,String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;concat;(String,String);;Argument[1];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;getBaseName;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;getExtension;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;getFullPath;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;getFullPathNoEndSeparator;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;getName;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;getPath;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;getPathNoEndSeparator;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;getPrefix;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;normalize;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;normalize;(String,boolean);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;normalizeNoEndSeparator;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;normalizeNoEndSeparator;(String,boolean);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;FilenameUtils;true;removeExtension;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;HexDump;true;dump;(byte[],long,OutputStream,int);;Argument[0];Argument[2];taint", - "org.apache.commons.io;IOExceptionList;true;IOExceptionList;(List);;Argument[0];Argument[-1];taint", - "org.apache.commons.io;IOExceptionList;true;IOExceptionList;(String,List);;Argument[1];Argument[-1];taint", - "org.apache.commons.io;IOExceptionList;true;getCause;(int);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;IOExceptionList;true;getCauseList;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;IOExceptionList;true;getCauseList;(Class);;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;buffer;(InputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;buffer;(InputStream,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;buffer;(OutputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;buffer;(OutputStream,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;buffer;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;buffer;(Reader,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;buffer;(Writer);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;buffer;(Writer,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(InputStream,OutputStream,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,Charset);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[2];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[2];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[4];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[4];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[2];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[4];taint", - "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[4];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,Charset);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;lineIterator;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;read;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;read;(Reader,char[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;read;(Reader,char[],int,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;readFully;(InputStream,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;readLines;(InputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;readLines;(InputStream,Charset);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;readLines;(InputStream,String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;readLines;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,long);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toByteArray;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,Charset);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toCharArray;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,Charset);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toInputStream;(String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toInputStream;(String,Charset);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toInputStream;(String,String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toString;(InputStream);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toString;(InputStream,Charset);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toString;(InputStream,String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toString;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toString;(byte[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toString;(byte[],String);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,Charset);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,String);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(CharSequence,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(String,OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,Charset);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,String);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(String,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream,String);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(StringBuffer,Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(byte[],OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(byte[],Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,Charset);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,String);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,Charset);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,String);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;write;(char[],Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;writeChunked;(char[],Writer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Argument[1];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,Charset);;Argument[1];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Argument[1];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[1];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;writer;(Appendable);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;LineIterator;true;LineIterator;(Reader);;Argument[0];Argument[-1];taint", - "org.apache.commons.io;LineIterator;true;nextLine;();;Argument[-1];ReturnValue;taint", - "org.apache.commons.io;TaggedIOException;true;TaggedIOException;(IOException,Serializable);;Argument[1];Argument[-1];taint", - "org.apache.commons.io;TaggedIOException;true;getTag;();;Argument[-1];ReturnValue;taint" + "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint", ] } } diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IOCustom.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IOCustom.qll deleted file mode 100644 index 89af5962a0e..00000000000 --- a/java/ql/lib/semmle/code/java/frameworks/apache/IOCustom.qll +++ /dev/null @@ -1,17 +0,0 @@ -/** Custom definitions related to the Apache Commons IO library. */ - -import java -private import semmle.code.java.dataflow.ExternalFlow - -// TODO: manual models that were not generated yet -private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[0];Argument[2];taint", - "org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint", - ] - } -} diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IOGenerated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IOGenerated.qll new file mode 100644 index 00000000000..87bdcf12ce6 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IOGenerated.qll @@ -0,0 +1,684 @@ +/** Definitions of taint steps in the IO framework */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +private class IOSinksCsv extends SinkModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io.file;PathFilter;true;accept;(Path,BasicFileAttributes);;Argument[0];create-file", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[0];open-url", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Argument[0];open-url", + "org.apache.commons.io.file;PathUtils;false;newOutputStream;(Path,boolean);;Argument[0];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filter;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filterList;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filterSet;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.input;Tailer$Tailable;true;getRandomAccess;(String);;Argument[-1];create-file", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(URL);;Argument[0];open-url", + "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,Charset);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,CharsetEncoder);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,CharsetEncoder,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,String);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,String,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,Charset);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,CharsetEncoder);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,CharsetEncoder,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,String);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,String,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File);;Argument[0];create-file", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter,boolean,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectoryToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,boolean,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFileToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFileToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyInputStreamToFile;(InputStream,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToDirectory;(Iterable,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToFile;(InputStream,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File);;Argument[0];open-url", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File,int,int);;Argument[0];open-url", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File,int,int);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveDirectoryToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFile;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFile;(File,File,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFileToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;newOutputStream;(File,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;openOutputStream;(File);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;openOutputStream;(File,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;touch;(File);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,Charset);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[]);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],int,int);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],int,int,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,Charset);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;IOUtils;true;copy;(URL,File);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;copy;(URL,File);;Argument[1];create-file", + "org.apache.commons.io;IOUtils;true;copy;(URL,OutputStream);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toByteArray;(URI);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toByteArray;(URL);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI,Charset);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI,String);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL,Charset);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL,String);;Argument[0];open-url", + "org.apache.commons.io;RandomAccessFileMode;false;create;(File);;Argument[0];create-file", + "org.apache.commons.io;RandomAccessFileMode;false;create;(Path);;Argument[0];create-file", + "org.apache.commons.io;RandomAccessFileMode;false;create;(String);;Argument[0];create-file" + ] + } +} + +private class IOSourcesCsv extends SourceModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io;IOUtils;true;resourceToByteArray;(String,ClassLoader);;ReturnValue;remote", + "org.apache.commons.io;IOUtils;true;toByteArray;(URI);;ReturnValue;remote" + ] + } +} + +private class IOSummaryCsv extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io.comparator;CompositeFileComparator;true;CompositeFileComparator;(Comparator[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.comparator;CompositeFileComparator;true;CompositeFileComparator;(Iterable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.comparator;CompositeFileComparator;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(String);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URI);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URL);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;getDirList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;getFileList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withBigIntegerCounters;(PathFilter,PathFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withBigIntegerCounters;(PathFilter,PathFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withLongCounters;(PathFilter,PathFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withLongCounters;(PathFilter,PathFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[4];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[5];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getCopyOptions;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getSourceDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getTargetDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getByteCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getDirectoryCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getFileCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;getPathCounters;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;DirectoryStreamFilter;true;DirectoryStreamFilter;(PathFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DirectoryStreamFilter;true;getPathFilter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyDirectory;(Path,Path,CopyOption[]);;ArrayElement of Argument[2];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyDirectory;(Path,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;delete;(Path,LinkOption[],DeleteOption[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;deleteDirectory;(Path,LinkOption[],DeleteOption[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;setReadOnly;(Path,boolean,LinkOption[]);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,Path);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,Path,Set,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,String,String[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,URI);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;writeString;(Path,CharSequence,Charset,OpenOption[]);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;AgeFileFilter;(Instant);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;AgeFileFilter;(Instant,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;addFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;addFileFilter;(IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;getFileFilters;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;setFileFilters;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;DelegateFileFilter;(FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;DelegateFileFilter;(FilenameFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileEqualsFileFilter;true;FileEqualsFileFilter;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;and;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;andFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;andFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;asFileFilter;(FileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;asFileFilter;(FilenameFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(String,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(byte[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(byte[],long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeCVSAware;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeDirectoryOnly;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeFileOnly;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeSVNAware;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;nameFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;nameFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;notFileFilter;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;or;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;orFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;orFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;prefixFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;prefixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;toList;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;negate;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(byte[],long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;NotFileFilter;true;NotFileFilter;(IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NotFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;addFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;PathEqualsFileFilter;true;PathEqualsFileFilter;(Path);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PathVisitorFileFilter;true;PathVisitorFileFilter;(PathVisitor);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern,Function);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern,Function);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;CircularBufferInputStream;true;CircularBufferInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;CircularBufferInputStream;true;CircularBufferInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;CircularByteBuffer;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.input.buffer;PeekableInputStream;true;PeekableInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;PeekableInputStream;true;PeekableInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BOMInputStream;true;BOMInputStream;(InputStream,ByteOrderMark[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;BOMInputStream;true;BOMInputStream;(InputStream,boolean,ByteOrderMark[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;BOMInputStream;true;getBOM;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;BOMInputStream;true;getBOMCharsetName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;BoundedInputStream;true;BoundedInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BoundedInputStream;true;BoundedInputStream;(InputStream,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BoundedReader;true;BoundedReader;(Reader,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BrokenInputStream;true;BrokenInputStream;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BrokenReader;true;BrokenReader;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;CharacterFilterReader;true;CharacterFilterReader;(Reader,IntPredicate);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;CircularInputStream;true;CircularInputStream;(byte[],long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ClassLoaderObjectInputStream;true;ClassLoaderObjectInputStream;(ClassLoader,InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ClassLoaderObjectInputStream;true;ClassLoaderObjectInputStream;(ClassLoader,InputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;CloseShieldInputStream;true;wrap;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;InfiniteCircularInputStream;true;InfiniteCircularInputStream;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream$MessageDigestMaintainingObserver;true;MessageDigestMaintainingObserver;(MessageDigest);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;MessageDigestCalculatingInputStream;(InputStream,MessageDigest);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;getMessageDigest;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ObservableInputStream;true;ObservableInputStream;(InputStream,Observer[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ObservableInputStream;true;add;(Observer);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ObservableInputStream;true;getObservers;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;RandomAccessFileInputStream;(RandomAccessFile);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;RandomAccessFileInputStream;(RandomAccessFile,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;getRandomAccessFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int,ExecutorService);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int,ExecutorService);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,Charset);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,Charset,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,String,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;readLine;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;readLines;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;toString;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;SequenceReader;true;SequenceReader;(Iterable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;SequenceReader;true;SequenceReader;(Reader[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(File,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(File,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Path,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Path,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Tailable,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Tailable,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;withBufferSize;(int);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withCharset;(Charset);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer$Builder;true;withReOpen;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withStartThread;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withTailFromEnd;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;create;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[2];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getDelayDuration;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getTailable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TeeInputStream;true;TeeInputStream;(InputStream,OutputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeInputStream;true;TeeInputStream;(InputStream,OutputStream,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeReader;true;TeeReader;(Reader,Writer);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeReader;true;TeeReader;(Reader,Writer,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TimestampedObserver;true;getCloseInstant;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TimestampedObserver;true;getOpenInstant;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TimestampedObserver;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;UncheckedBufferedReader;(Reader);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;UncheckedBufferedReader;(Reader,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;on;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;UncheckedFilterInputStream;true;on;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;UnixLineEndingInputStream;true;UnixLineEndingInputStream;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[],int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;WindowsLineEndingInputStream;true;WindowsLineEndingInputStream;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(URLConnection,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReader;true;getEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[4];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[5];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getBomEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeMime;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlGuessEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;FileAlterationMonitor;(long,Collection);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;FileAlterationMonitor;(long,FileAlterationObserver[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;addObserver;(FileAlterationObserver);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;getObservers;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;setThreadFactory;(ThreadFactory);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter,IOCase);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter,IOCase);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;addListener;(FileAlterationListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getFileFilter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getListeners;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(FileEntry,File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(FileEntry,File);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;getChildren;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getLastModifiedFileTime;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getParent;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;setChildren;(FileEntry[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;setLastModified;(FileTime);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;setName;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toByteArray;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(Charset);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(String);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;write;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.output;AppendableOutputStream;true;AppendableOutputStream;(Appendable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;AppendableOutputStream;true;getAppendable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AppendableWriter;true;AppendableWriter;(Appendable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;AppendableWriter;true;getAppendable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;BrokenOutputStream;true;BrokenOutputStream;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;BrokenWriter;true;BrokenWriter;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ChunkedOutputStream;true;ChunkedOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ChunkedOutputStream;true;ChunkedOutputStream;(OutputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;CloseShieldOutputStream;true;CloseShieldOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;CloseShieldOutputStream;true;wrap;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;CountingOutputStream;true;CountingOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,File);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[4];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;getData;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,Charset,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,String,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(String,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;ProxyCollectionWriter;true;ProxyCollectionWriter;(Collection);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ProxyCollectionWriter;true;ProxyCollectionWriter;(Writer[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ProxyOutputStream;true;ProxyOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;StringBuilderWriter;true;StringBuilderWriter;(StringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;StringBuilderWriter;true;getBuilder;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;StringBuilderWriter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;TaggedOutputStream;true;TaggedOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeOutputStream;true;TeeOutputStream;(OutputStream,OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeOutputStream;true;TeeOutputStream;(OutputStream,OutputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;TeeWriter;true;TeeWriter;(Collection);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeWriter;true;TeeWriter;(Writer[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ThresholdingOutputStream;true;ThresholdingOutputStream;(int,IOConsumer,IOFunction);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;ThresholdingOutputStream;true;ThresholdingOutputStream;(int,IOConsumer,IOFunction);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;UncheckedAppendable;true;on;(Appendable);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;UncheckedFilterOutputStream;true;UncheckedFilterOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;UncheckedFilterOutputStream;true;on;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,Charset);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,Charset,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder,int,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,String,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;XmlStreamWriter;true;getEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;ValidatingObjectInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Class[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Class[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;ByteOrderMark;true;ByteOrderMark;(String,int[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;ByteOrderMark;true;getCharsetName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;ByteOrderMark;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(String,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(File,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(String,File,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileCleaningTracker;true;getDeleteFailures;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(File,Object,FileDeleteStrategy);;Argument[2];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object,FileDeleteStrategy);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object,FileDeleteStrategy);;Argument[2];Argument[-1];taint", + "org.apache.commons.io;FileDeleteStrategy;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileSystem;false;toLegalFileName;(String,char);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;checksum;(File,Checksum);;Argument[1];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;convertFileCollectionToFileArray;(Collection);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;delete;(File);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(File,String[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(File,String[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;toURLs;(File[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;concat;(String,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;concat;(String,String);;Argument[1];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getBaseName;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getExtension;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getFullPath;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getFullPathNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getName;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPath;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPathNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPrefix;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalize;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalize;(String,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalizeNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalizeNoEndSeparator;(String,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;removeExtension;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;HexDump;true;dump;(byte[],long,OutputStream,int);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOExceptionList;true;IOExceptionList;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;IOExceptionList;true;IOExceptionList;(String,List);;Argument[1];Argument[-1];taint", + "org.apache.commons.io;IOExceptionList;true;getCause;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOExceptionList;true;getCauseList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOExceptionList;true;getCauseList;(Class);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(OutputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Reader,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Writer);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Writer,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,OutputStream,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[4];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[4];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[4];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[4];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(Reader,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(Reader,char[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(byte[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(byte[],String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeChunked;(char[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,Charset);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writer;(Appendable);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;LineIterator;true;LineIterator;(Reader);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;LineIterator;true;nextLine;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;TaggedIOException;true;TaggedIOException;(IOException,Serializable);;Argument[1];Argument[-1];taint", + "org.apache.commons.io;TaggedIOException;true;getTag;();;Argument[-1];ReturnValue;taint" + ] + } +} From 97d9985e0b3849e31f64821a5e3b021ae15da38a Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 20 Jan 2022 13:10:19 +0100 Subject: [PATCH 150/196] C#: Add support for flow via object initializer for anonymous types. --- .../dataflow/internal/DataFlowPrivate.qll | 2 ++ .../test/library-tests/dataflow/fields/F.cs | 11 ++++++++++- .../dataflow/fields/FieldFlow.expected | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index cdf3923c195..5bdf9b3c0de 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1481,6 +1481,8 @@ class FieldOrProperty extends Assignable, Modifiable { p.isAutoImplemented() or p.matchesHandle(any(CIL::TrivialProperty tp)) + or + p.getDeclaringType() instanceof AnonymousClass ) ) } diff --git a/csharp/ql/test/library-tests/dataflow/fields/F.cs b/csharp/ql/test/library-tests/dataflow/fields/F.cs index 2e7cd9b6e2c..3754dff53ff 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/F.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/F.cs @@ -5,7 +5,7 @@ public class F static F Create(object o1, object o2) => new F() { Field1 = o1, Field2 = o2 }; - private void M() + private void M1() { var o = Source(1); var f = Create(o, null); @@ -25,6 +25,15 @@ public class F Sink(f.Field2); // $ hasValueFlow=4 } + private void M2() + { + var o = Source(2); + object @null = null; + var a = new { X = o, Y = @null }; + Sink(a.X); // $ hasValueFlow=2 + Sink(a.Y); // no flow + } + public static void Sink(object o) { } static T Source(object source) => throw null; diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index 836f3dfdf7f..db69c9e7c88 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -456,6 +456,14 @@ edges | F.cs:23:32:23:48 | call to method Source : Object | F.cs:23:21:23:50 | { ..., ... } [field Field2] : Object | | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | F.cs:25:14:25:21 | access to field Field2 | | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | F.cs:25:14:25:21 | access to field Field2 | +| F.cs:30:17:30:33 | call to method Source : Object | F.cs:32:27:32:27 | access to local variable o : Object | +| F.cs:30:17:30:33 | call to method Source : Object | F.cs:32:27:32:27 | access to local variable o : Object | +| F.cs:32:17:32:40 | { ..., ... } [property X] : Object | F.cs:33:14:33:14 | access to local variable a [property X] : Object | +| F.cs:32:17:32:40 | { ..., ... } [property X] : Object | F.cs:33:14:33:14 | access to local variable a [property X] : Object | +| F.cs:32:27:32:27 | access to local variable o : Object | F.cs:32:17:32:40 | { ..., ... } [property X] : Object | +| F.cs:32:27:32:27 | access to local variable o : Object | F.cs:32:17:32:40 | { ..., ... } [property X] : Object | +| F.cs:33:14:33:14 | access to local variable a [property X] : Object | F.cs:33:14:33:16 | access to property X | +| F.cs:33:14:33:14 | access to local variable a [property X] : Object | F.cs:33:14:33:16 | access to property X | | G.cs:7:18:7:32 | call to method Source : Elem | G.cs:9:23:9:23 | access to local variable e : Elem | | G.cs:7:18:7:32 | call to method Source : Elem | G.cs:9:23:9:23 | access to local variable e : Elem | | G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:10:18:10:18 | access to local variable b [field Box1, field Elem] : Elem | @@ -1367,6 +1375,16 @@ nodes | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | semmle.label | access to local variable f [field Field2] : Object | | F.cs:25:14:25:21 | access to field Field2 | semmle.label | access to field Field2 | | F.cs:25:14:25:21 | access to field Field2 | semmle.label | access to field Field2 | +| F.cs:30:17:30:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| F.cs:30:17:30:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| F.cs:32:17:32:40 | { ..., ... } [property X] : Object | semmle.label | { ..., ... } [property X] : Object | +| F.cs:32:17:32:40 | { ..., ... } [property X] : Object | semmle.label | { ..., ... } [property X] : Object | +| F.cs:32:27:32:27 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:32:27:32:27 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:33:14:33:14 | access to local variable a [property X] : Object | semmle.label | access to local variable a [property X] : Object | +| F.cs:33:14:33:14 | access to local variable a [property X] : Object | semmle.label | access to local variable a [property X] : Object | +| F.cs:33:14:33:16 | access to property X | semmle.label | access to property X | +| F.cs:33:14:33:16 | access to property X | semmle.label | access to property X | | G.cs:7:18:7:32 | call to method Source : Elem | semmle.label | call to method Source : Elem | | G.cs:7:18:7:32 | call to method Source : Elem | semmle.label | call to method Source : Elem | | G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | @@ -1952,6 +1970,7 @@ subpaths | F.cs:17:14:17:21 | access to field Field2 | F.cs:15:26:15:42 | call to method Source : Object | F.cs:17:14:17:21 | access to field Field2 | $@ | F.cs:15:26:15:42 | call to method Source : Object | call to method Source : Object | | F.cs:20:14:20:21 | access to field Field1 | F.cs:19:32:19:48 | call to method Source : Object | F.cs:20:14:20:21 | access to field Field1 | $@ | F.cs:19:32:19:48 | call to method Source : Object | call to method Source : Object | | F.cs:25:14:25:21 | access to field Field2 | F.cs:23:32:23:48 | call to method Source : Object | F.cs:25:14:25:21 | access to field Field2 | $@ | F.cs:23:32:23:48 | call to method Source : Object | call to method Source : Object | +| F.cs:33:14:33:16 | access to property X | F.cs:30:17:30:33 | call to method Source : Object | F.cs:33:14:33:16 | access to property X | $@ | F.cs:30:17:30:33 | call to method Source : Object | call to method Source : Object | | G.cs:39:14:39:35 | call to method GetElem | G.cs:7:18:7:32 | call to method Source : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:7:18:7:32 | call to method Source : Elem | call to method Source : Elem | | G.cs:39:14:39:35 | call to method GetElem | G.cs:15:18:15:32 | call to method Source : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:15:18:15:32 | call to method Source : Elem | call to method Source : Elem | | G.cs:39:14:39:35 | call to method GetElem | G.cs:23:18:23:32 | call to method Source : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:23:18:23:32 | call to method Source : Elem | call to method Source : Elem | From e804922a2c774745d527eaae925f21cfc48c9ada Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 20 Jan 2022 13:14:06 +0100 Subject: [PATCH 151/196] C#: Add flow test case for with expressions on anonymous types. --- .../dataflow/fields/FieldFlow.expected | 43 +++++++++++++++++++ .../test/library-tests/dataflow/fields/J.cs | 19 ++++++++ 2 files changed, 62 insertions(+) diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index db69c9e7c88..9d18b7ebad4 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -876,6 +876,24 @@ edges | J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | J.cs:87:14:87:21 | access to field Field | | J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | J.cs:88:14:88:20 | access to property Prop | | J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | J.cs:88:14:88:20 | access to property Prop | +| J.cs:97:17:97:33 | call to method Source : Object | J.cs:99:28:99:28 | access to local variable o : Object | +| J.cs:97:17:97:33 | call to method Source : Object | J.cs:99:28:99:28 | access to local variable o : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | +| J.cs:99:28:99:28 | access to local variable o : Object | J.cs:99:18:99:41 | { ..., ... } [property X] : Object | +| J.cs:99:28:99:28 | access to local variable o : Object | J.cs:99:18:99:41 | { ..., ... } [property X] : Object | +| J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | J.cs:102:14:102:17 | access to property X | +| J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | J.cs:102:14:102:17 | access to property X | +| J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | +| J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | +| J.cs:105:32:105:48 | call to method Source : Object | J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | +| J.cs:105:32:105:48 | call to method Source : Object | J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | +| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | J.cs:106:14:106:17 | access to property X | +| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | J.cs:106:14:106:17 | access to property X | +| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | J.cs:107:14:107:17 | access to property Y | +| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | J.cs:107:14:107:17 | access to property Y | 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 | @@ -1833,6 +1851,28 @@ nodes | J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | | J.cs:88:14:88:20 | access to property Prop | semmle.label | access to property Prop | | J.cs:88:14:88:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:97:17:97:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:97:17:97:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | semmle.label | { ..., ... } [property X] : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | semmle.label | { ..., ... } [property X] : Object | +| J.cs:99:28:99:28 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:99:28:99:28 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | semmle.label | access to local variable a2 [property X] : Object | +| J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | semmle.label | access to local variable a2 [property X] : Object | +| J.cs:102:14:102:17 | access to property X | semmle.label | access to property X | +| J.cs:102:14:102:17 | access to property X | semmle.label | access to property X | +| J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | semmle.label | ... with { ... } [property Y] : Object | +| J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | semmle.label | ... with { ... } [property Y] : Object | +| J.cs:105:32:105:48 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:105:32:105:48 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | semmle.label | access to local variable a3 [property X] : Object | +| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | semmle.label | access to local variable a3 [property X] : Object | +| J.cs:106:14:106:17 | access to property X | semmle.label | access to property X | +| J.cs:106:14:106:17 | access to property X | semmle.label | access to property X | +| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | semmle.label | access to local variable a3 [property Y] : Object | +| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | semmle.label | access to local variable a3 [property Y] : Object | +| J.cs:107:14:107:17 | access to property Y | semmle.label | access to property Y | +| J.cs:107:14:107:17 | access to property Y | semmle.label | access to property Y | 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 | @@ -2004,3 +2044,6 @@ subpaths | J.cs:84:14:84:20 | access to property Prop | J.cs:79:17:79:33 | call to method Source : Object | J.cs:84:14:84:20 | access to property Prop | $@ | J.cs:79:17:79:33 | call to method Source : Object | call to method Source : Object | | J.cs:87:14:87:21 | access to field Field | J.cs:86:36:86:52 | call to method Source : Object | J.cs:87:14:87:21 | access to field Field | $@ | J.cs:86:36:86:52 | call to method Source : Object | call to method Source : Object | | J.cs:88:14:88:20 | access to property Prop | J.cs:79:17:79:33 | call to method Source : Object | J.cs:88:14:88:20 | access to property Prop | $@ | J.cs:79:17:79:33 | call to method Source : Object | call to method Source : Object | +| J.cs:102:14:102:17 | access to property X | J.cs:97:17:97:33 | call to method Source : Object | J.cs:102:14:102:17 | access to property X | $@ | J.cs:97:17:97:33 | call to method Source : Object | call to method Source : Object | +| J.cs:106:14:106:17 | access to property X | J.cs:97:17:97:33 | call to method Source : Object | J.cs:106:14:106:17 | access to property X | $@ | J.cs:97:17:97:33 | call to method Source : Object | call to method Source : Object | +| J.cs:107:14:107:17 | access to property Y | J.cs:105:32:105:48 | call to method Source : Object | J.cs:107:14:107:17 | access to property Y | $@ | J.cs:105:32:105:48 | 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 0aeed7eb1a7..18a85890b91 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/J.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs @@ -92,6 +92,25 @@ public class J Sink(s4.Prop); // no flow } + private void M5() + { + var o = Source(7); + object @null = null; + var a1 = new { X = o, Y = @null }; + + var a2 = a1 with { }; + Sink(a2.X); // $ hasValueFlow=7 + Sink(a2.Y); // no flow + + var a3 = a1 with { Y = Source(8) }; + Sink(a3.X); // $ hasValueFlow=7 + Sink(a3.Y); // $ hasValueFlow=8 + + var a4 = a1 with { X = @null }; + Sink(a4.X); // no flow + Sink(a4.Y); // no flow + } + public static void Sink(object o) { } static T Source(object source) => throw null; From ec8ffeed072821de635bc662f9bdd0b413418f4a Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 27 Oct 2021 13:12:08 +0200 Subject: [PATCH 152/196] Add Intent URI Permission Manipulation query --- .../dataflow/internal/TaintTrackingUtil.qll | 5 + .../code/java/frameworks/android/Android.qll | 8 ++ .../code/java/frameworks/android/Intent.qll | 25 +++++ .../IntentUriPermissionManipulation.qll | 101 ++++++++++++++++++ .../IntentUriPermissionManipulationQuery.qll | 30 ++++++ .../lib/semmle/code/xml/AndroidManifest.qll | 15 +++ .../IntentUriPermissionManipulation.ql | 24 +++++ .../security/CWE-266/AndroidManifest.xml | 22 ++++ ...tentUriPermissionManipulationTest.expected | 0 .../IntentUriPermissionManipulationTest.ql | 11 ++ .../security/CWE-266/MainActivity.java | 85 +++++++++++++++ .../test/query-tests/security/CWE-266/options | 1 + 12 files changed, 327 insertions(+) create mode 100644 java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll create mode 100644 java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll create mode 100644 java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql create mode 100755 java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml create mode 100644 java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected create mode 100644 java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql create mode 100644 java/ql/test/query-tests/security/CWE-266/MainActivity.java create mode 100644 java/ql/test/query-tests/security/CWE-266/options diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index b1840e56212..20803508a0d 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -176,6 +176,8 @@ private predicate localAdditionalTaintExprStep(Expr src, Expr sink) { serializationStep(src, sink) or formatStep(src, sink) + or + bitwiseStep(src, sink) } /** @@ -525,6 +527,9 @@ private class FormatterCallable extends TaintPreservingCallable { } } +/** Holds if taint may flow from the operand of a bitwise expression to its result. */ +private predicate bitwiseStep(Expr src, BitwiseExpr sink) { sink.(BinaryExpr).getAnOperand() = src } + private import StringBuilderVarModule module StringBuilderVarModule { diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index c019dc11bd8..41ad2d14968 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -67,6 +67,14 @@ class AndroidActivity extends ExportableAndroidComponent { AndroidActivity() { getASuperTypeStar(this).hasQualifiedName("android.app", "Activity") } } +/** The method `setResult` of the class `android.app.Activity`. */ +class ActivitySetResultMethod extends Method { + ActivitySetResultMethod() { + this.getDeclaringType().hasQualifiedName("android.app", "Activity") and + this.hasName("setResult") + } +} + /** An Android service. */ class AndroidService extends ExportableAndroidComponent { AndroidService() { getASuperTypeStar(this).hasQualifiedName("android.app", "Service") } diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index d77e4a5b86d..51f3b577420 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -148,6 +148,31 @@ predicate allowIntentExtrasImplicitRead(DataFlow::Node node, DataFlow::Content c ) } +/** + * The fields to grant URI permissions of the class `android.content.Intent`: + * + * - `Intent.FLAG_GRANT_READ_URI_PERMISSION` + * - `Intent.FLAG_GRANT_WRITE_URI_PERMISSION` + * - `Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION` + * - `Intent.FLAG_GRANT_PREFIX_URI_PERMISSION` + */ +class GrantUriPermissionFlag extends Field { + GrantUriPermissionFlag() { + this.getDeclaringType() instanceof TypeIntent and + this.getName().matches("FLAG_GRANT_%_URI_PERMISSION") + } +} + +/** The field `Intent.FLAG_GRANT_READ_URI_PERMISSION`. */ +class GrantReadUriPermissionFlag extends GrantUriPermissionFlag { + GrantReadUriPermissionFlag() { this.hasName("FLAG_GRANT_READ_URI_PERMISSION") } +} + +/** The field `Intent.FLAG_GRANT_WRITE_URI_PERMISSION`. */ +class GrantWriteUriPermissionFlag extends GrantUriPermissionFlag { + GrantWriteUriPermissionFlag() { this.hasName("FLAG_GRANT_WRITE_URI_PERMISSION") } +} + private class IntentBundleFlowSteps extends SummaryModelCsv { override predicate row(string row) { row = diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll new file mode 100644 index 00000000000..cf273abbbe5 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -0,0 +1,101 @@ +/** + * Provides classes and predicates to reason about Intent URI permission manipulation + * vulnerabilities on Android. + */ + +import java +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.TaintTracking +private import semmle.code.java.frameworks.android.Android +private import semmle.code.java.frameworks.android.Intent + +/** + * A sink for Intent URI permission manipulation vulnerabilities in Android, + * that is, method calls that return an Intent as the result of an Activity. + */ +abstract class IntentUriPermissionManipulationSink extends DataFlow::Node { } + +/** + * A sanitizer that makes sure that an Intent is safe to be returned to another Activity. + * + * Usually, this is done by setting the Intent's data URI and/or its flags to safe values. + */ +abstract class IntentUriPermissionManipulationSanitizer extends DataFlow::Node { } + +/** + * A guard that makes sure that an Intent is safe to be returned to another Activity. + * + * Usually, this is done by checking that the Intent's data URI and/or its flags contain + * expected values. + */ +abstract class IntentUriPermissionManipulationGuard extends DataFlow::BarrierGuard { } + +private class DefaultIntentUriPermissionManipulationSink extends IntentUriPermissionManipulationSink { + DefaultIntentUriPermissionManipulationSink() { + exists(MethodAccess ma | ma.getMethod() instanceof ActivitySetResultMethod | + ma.getArgument(1) = this.asExpr() + ) + } +} + +private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManipulationSanitizer { + IntentFlagsOrDataChangedSanitizer() { + exists(MethodAccess ma, Method m | + ma.getMethod() = m and + m.getDeclaringType() instanceof TypeIntent and + this.asExpr() = ma.getQualifier() + | + m.hasName("removeFlags") and + TaintTracking::localExprTaint(any(GrantReadUriPermissionFlag f).getAnAccess(), + ma.getArgument(0)) and + TaintTracking::localExprTaint(any(GrantWriteUriPermissionFlag f).getAnAccess(), + ma.getArgument(0)) + or + ma.getMethod() = m and + m.getDeclaringType() instanceof TypeIntent and + this.asExpr() = ma.getQualifier() and + m.hasName("setFlags") and + not TaintTracking::localExprTaint(any(GrantUriPermissionFlag f).getAnAccess(), + ma.getArgument(0)) + or + m.hasName("setData") + ) + } +} + +private class IntentFlagsOrDataCheckedGuard extends IntentUriPermissionManipulationGuard { + Expr condition; + + IntentFlagsOrDataCheckedGuard() { + this.(MethodAccess).getMethod() instanceof EqualsMethod and + condition = [this.(MethodAccess).getArgument(0), this.(MethodAccess).getQualifier()] + or + condition = this.(EqualityTest).getAnOperand().(AndBitwiseExpr) + } + + override predicate checks(Expr e, boolean branch) { + exists(MethodAccess ma, Method m | + ma.getMethod() = m and + m.getDeclaringType() instanceof TypeIntent and + m.hasName(["getFlags", "getData"]) and + TaintTracking::localExprTaint(ma, condition) and + ma.getQualifier() = e + | + bitwiseCheck(branch) + or + this.(MethodAccess).getMethod() instanceof EqualsMethod and branch = true + ) + } + + /** + * Holds if `this` is a bitwise check. `branch` is `true` when the expected value is `0` + * and `false` otherwise. + */ + private predicate bitwiseCheck(boolean branch) { + exists(CompileTimeConstantExpr operand | operand = this.(EqualityTest).getAnOperand() | + if operand.getIntValue() = 0 + then this.(EqualityTest).polarity() = branch + else this.(EqualityTest).polarity().booleanNot() = branch + ) + } +} diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll new file mode 100644 index 00000000000..ab7ff6540ae --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll @@ -0,0 +1,30 @@ +/** + * Provides taint tracking configurations to be used in queries related to Intent URI permission + * manipulation in Android. + */ + +import java +private import semmle.code.java.dataflow.FlowSources +private import semmle.code.java.dataflow.DataFlow +private import IntentUriPermissionManipulation + +/** + * A taint tracking configuration for user-provided Intents being returned to third party apps. + */ +class IntentUriPermissionManipulationConf extends TaintTracking::Configuration { + IntentUriPermissionManipulationConf() { this = "UriPermissionManipulationConf" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof IntentUriPermissionManipulationSink + } + + override predicate isSanitizer(DataFlow::Node barrier) { + barrier instanceof IntentUriPermissionManipulationSanitizer + } + + override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { + guard instanceof IntentUriPermissionManipulationGuard + } +} diff --git a/java/ql/lib/semmle/code/xml/AndroidManifest.qll b/java/ql/lib/semmle/code/xml/AndroidManifest.qll index 234aacca967..81b3c44e62b 100644 --- a/java/ql/lib/semmle/code/xml/AndroidManifest.qll +++ b/java/ql/lib/semmle/code/xml/AndroidManifest.qll @@ -74,6 +74,13 @@ class AndroidReceiverXmlElement extends AndroidComponentXmlElement { AndroidReceiverXmlElement() { this.getName() = "receiver" } } +/** + * An XML attribute with the `android:` prefix. + */ +class AndroidXmlAttribute extends XMLAttribute { + AndroidXmlAttribute() { this.getNamespace().getPrefix() = "android" } +} + /** * A `` element in an Android manifest file. */ @@ -91,6 +98,14 @@ class AndroidProviderXmlElement extends AndroidComponentXmlElement { this.getAnAttribute().(AndroidPermissionXmlAttribute).isWrite() and this.getAnAttribute().(AndroidPermissionXmlAttribute).isRead() } + + predicate grantsUriPermissions() { + exists(AndroidXmlAttribute attr | + this.getAnAttribute() = attr and + attr.getName() = "grantUriPermissions" and + attr.getValue() = "true" + ) + } } /** diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql new file mode 100644 index 00000000000..b722e4312be --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql @@ -0,0 +1,24 @@ +/** + * @name Intent URI permission manipulation + * @description When an externally provided Intent is returned to an Activity via setResult, + * a malicious application could use this to grant itself permissions to access + * arbitrary Content Providers that are accessible by the vulnerable application. + * @kind path-problem + * @problem.severity error + * @precision high + * @id java/android/intent-uri-permission-manipulation + * @tags security + * external/cwe/cwe-266 + * external/cwe/cwe-926 + */ + +import java +import semmle.code.java.security.IntentUriPermissionManipulationQuery +import semmle.code.java.dataflow.DataFlow +import DataFlow::PathGraph + +from DataFlow::PathNode source, DataFlow::PathNode sink +where any(IntentUriPermissionManipulationConf c).hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "This Intent can be set with arbitrary flags from $@, " + + "and used to give access to internal Content Providers.", source.getNode(), "this user input" diff --git a/java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml new file mode 100755 index 00000000000..cff71a75235 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql new file mode 100644 index 00000000000..72b95d874d2 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql @@ -0,0 +1,11 @@ +import java +import TestUtilities.InlineFlowTest +import semmle.code.java.security.IntentUriPermissionManipulationQuery + +class IntentUriPermissionManipulationTest extends InlineFlowTest { + override DataFlow::Configuration getValueFlowConfig() { none() } + + override TaintTracking::Configuration getTaintFlowConfig() { + result instanceof IntentUriPermissionManipulationConf + } +} diff --git a/java/ql/test/query-tests/security/CWE-266/MainActivity.java b/java/ql/test/query-tests/security/CWE-266/MainActivity.java new file mode 100644 index 00000000000..4af80cc2b18 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-266/MainActivity.java @@ -0,0 +1,85 @@ +package com.example.app; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +public class MainActivity extends Activity { + + public void onCreate(Bundle savedInstance) { + { + Intent intent = getIntent(); + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + { + Intent extraIntent = (Intent) getIntent().getParcelableExtra("extraIntent"); + setResult(RESULT_OK, extraIntent); // $ hasTaintFlow + } + { + Intent intent = getIntent(); + intent.setData(Uri.parse("content://safe/uri")); // Sanitizer + setResult(RESULT_OK, intent); // Safe + } + { + Intent intent = getIntent(); + intent.setFlags(0); // Sanitizer + setResult(RESULT_OK, intent); // Safe + } + { + Intent intent = getIntent(); + intent.setFlags( // Not properly sanitized + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP); + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + { + Intent intent = getIntent(); + intent.removeFlags( // Sanitizer + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); + setResult(RESULT_OK, intent); // Safe + } + { + Intent intent = getIntent(); + // Combined, the following two calls are a sanitizer + intent.removeFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.removeFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + setResult(RESULT_OK, intent); // $ SPURIOUS: $ hasTaintFlow + } + { + Intent intent = getIntent(); + intent.removeFlags( // Not properly sanitized + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP); + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + { + Intent intent = getIntent(); + // Good check + if (intent.getData().equals(Uri.parse("content://safe/uri"))) { + setResult(RESULT_OK, intent); // Safe + } else { + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + } + { + Intent intent = getIntent(); + int flags = intent.getFlags(); + // Good check + if ((flags & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0 + && (flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { + setResult(RESULT_OK, intent); // Safe + } else { + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + } + { + Intent intent = getIntent(); + int flags = intent.getFlags(); + // Insufficient check + if ((flags & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { + setResult(RESULT_OK, intent); // $ MISSING: $ hasTaintFlow + } else { + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + } + } +} diff --git a/java/ql/test/query-tests/security/CWE-266/options b/java/ql/test/query-tests/security/CWE-266/options new file mode 100644 index 00000000000..dacd3cb21df --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-266/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0 From e1d30ebc09dde1c09389921e4b1959653b045742 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 27 Oct 2021 14:00:10 +0200 Subject: [PATCH 153/196] Added severity Removed duplicated code --- .../code/java/security/IntentUriPermissionManipulation.qll | 3 --- .../Security/CWE/CWE-266/IntentUriPermissionManipulation.ql | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll index cf273abbbe5..34194e0d074 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -51,9 +51,6 @@ private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManip TaintTracking::localExprTaint(any(GrantWriteUriPermissionFlag f).getAnAccess(), ma.getArgument(0)) or - ma.getMethod() = m and - m.getDeclaringType() instanceof TypeIntent and - this.asExpr() = ma.getQualifier() and m.hasName("setFlags") and not TaintTracking::localExprTaint(any(GrantUriPermissionFlag f).getAnAccess(), ma.getArgument(0)) diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql index b722e4312be..fceb4569505 100644 --- a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql @@ -5,6 +5,7 @@ * arbitrary Content Providers that are accessible by the vulnerable application. * @kind path-problem * @problem.severity error + * @security-severity 7.8 * @precision high * @id java/android/intent-uri-permission-manipulation * @tags security From 6152c8a989d8a4294698b911b177324259a3e1dc Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 4 Nov 2021 11:06:35 +0100 Subject: [PATCH 154/196] Add change note --- ...0-27-android-intent-uri-permission-manipulation-query.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md diff --git a/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md b/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md new file mode 100644 index 00000000000..9644ce80453 --- /dev/null +++ b/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md @@ -0,0 +1,6 @@ +--- +category: newQuery +--- +* A new query "Intent URI permission manipulation" (`java/android/intent-uri-permission-manipulation`) has been added. +This query finds Android components returning unmodified, received Intents to the calling applications, which +can provide unintended access to internal Content Providers of the victim application. \ No newline at end of file From 3405db31b86eb333d283a482e5fccba864d9309d Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 11 Nov 2021 09:54:14 +0100 Subject: [PATCH 155/196] Add qhelp --- .../IntentUriPermissionManipulation.java | 25 ++++++++++++++ .../IntentUriPermissionManipulation.qhelp | 34 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.java create mode 100644 java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.java b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.java new file mode 100644 index 00000000000..4d53add78c2 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.java @@ -0,0 +1,25 @@ +public class IntentUriPermissionManipulation extends Activity { + + // BAD: the user-provided Intent is returned as-is + public void dangerous() { + Intent intent = getIntent(); + intent.putExtra("result", "resultData"); + setResult(intent); + } + + // GOOD: a new Intent is created and returned + public void safe() { + Intent intent = new Intent(); + intent.putExtra("result", "resultData"); + setResult(intent); + } + + // GOOD: the user-provided Intent is sanitized before being returned + public void sanitized() { + Intent intent = getIntent(); + intent.putExtra("result", "resultData"); + intent.removeFlags( + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); + setResult(intent); + } +} diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp new file mode 100644 index 00000000000..75b4d13bf48 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp @@ -0,0 +1,34 @@ + + + +

    When an Android component expects a result from an Activity, startActivityForResult can be used. +The started Activity can then use setResult to return the appropriate data to the calling component.

    +

    If an Activity obtains the incoming, user-provided Intent and directly returns it via setResult +without any checks, the application may be unintentionally giving arbitrary access to its Content Providers, even +if they are not exported, as long as they are configured with the attribute android:grantUriPermissions="true". +This happens because the attacker adds the appropriate URI permission flags to the provided Intent, which take effect +once the Intent is reflected back.

    +
    + + +

    Avoid returning user-provided or untrusted Intents via setResult. Use a new Intent instead.

    +

    If it is required to use the received Intent, make sure that it does not contain URI permission flags, either +by checking them with Intent.getFlags or removing them with Intent.removeFlags.

    +
    + + +

    The following sample contains three examples. In the first example, a user-provided Intent is obtained and + directly returned back with setResult, which is dangerous. In the second example, a new Intent + is created to safely return the desired data. The third example shows how the obtained Intent can be sanitized + by removing dangerous flags before using it to return data to the calling component. +

    + + +
    + + +
  • Google Help: Remediation for Intent Redirection Vulnerability.
  • +
    +
    From ab560234e3247111144950c25abcfb9c656fbb3b Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 22 Nov 2021 15:27:11 +0100 Subject: [PATCH 156/196] Update java/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com> --- ...21-10-27-android-intent-uri-permission-manipulation-query.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md b/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md index 9644ce80453..0da4c4189f6 100644 --- a/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md +++ b/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md @@ -2,5 +2,5 @@ category: newQuery --- * A new query "Intent URI permission manipulation" (`java/android/intent-uri-permission-manipulation`) has been added. -This query finds Android components returning unmodified, received Intents to the calling applications, which +This query finds Android components that return unmodified, received Intents to the calling applications, which can provide unintended access to internal Content Providers of the victim application. \ No newline at end of file From 596cfd399e8a80e35a3474513b663c8f2b5f46e8 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 22 Nov 2021 15:51:15 +0100 Subject: [PATCH 157/196] Improve description --- .../Security/CWE/CWE-266/IntentUriPermissionManipulation.ql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql index fceb4569505..3cde1287e4a 100644 --- a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql @@ -1,8 +1,7 @@ /** * @name Intent URI permission manipulation - * @description When an externally provided Intent is returned to an Activity via setResult, - * a malicious application could use this to grant itself permissions to access - * arbitrary Content Providers that are accessible by the vulnerable application. + * @description Returning an externally provided Intent via setResult may allow a malicious + * application to access arbitrary Content Providers of the vulnerable application. * @kind path-problem * @problem.severity error * @security-severity 7.8 From 8767d2db230d1bb000d43de1fe6e85225dabb6d9 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Tue, 23 Nov 2021 11:11:23 +0100 Subject: [PATCH 158/196] Don't capitalize the term content provider Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com> --- .../CWE/CWE-266/IntentUriPermissionManipulation.qhelp | 2 +- .../Security/CWE/CWE-266/IntentUriPermissionManipulation.ql | 6 +++--- ...0-27-android-intent-uri-permission-manipulation-query.md | 2 +- .../frameworks/android/content-provider/Safe.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp index 75b4d13bf48..5577cf7cdb8 100644 --- a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp @@ -6,7 +6,7 @@

    When an Android component expects a result from an Activity, startActivityForResult can be used. The started Activity can then use setResult to return the appropriate data to the calling component.

    If an Activity obtains the incoming, user-provided Intent and directly returns it via setResult -without any checks, the application may be unintentionally giving arbitrary access to its Content Providers, even +without any checks, the application may be unintentionally giving arbitrary access to its content providers, even if they are not exported, as long as they are configured with the attribute android:grantUriPermissions="true". This happens because the attacker adds the appropriate URI permission flags to the provided Intent, which take effect once the Intent is reflected back.

    diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql index 3cde1287e4a..b108da2f1de 100644 --- a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql @@ -1,7 +1,7 @@ /** * @name Intent URI permission manipulation - * @description Returning an externally provided Intent via setResult may allow a malicious - * application to access arbitrary Content Providers of the vulnerable application. + * @description Returning an externally provided Intent via 'setResult' may allow a malicious + * application to access arbitrary content providers of the vulnerable application. * @kind path-problem * @problem.severity error * @security-severity 7.8 @@ -21,4 +21,4 @@ from DataFlow::PathNode source, DataFlow::PathNode sink where any(IntentUriPermissionManipulationConf c).hasFlowPath(source, sink) select sink.getNode(), source, sink, "This Intent can be set with arbitrary flags from $@, " + - "and used to give access to internal Content Providers.", source.getNode(), "this user input" + "and used to give access to internal content providers.", source.getNode(), "this user input" diff --git a/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md b/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md index 0da4c4189f6..fddecd1b953 100644 --- a/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md +++ b/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md @@ -3,4 +3,4 @@ category: newQuery --- * A new query "Intent URI permission manipulation" (`java/android/intent-uri-permission-manipulation`) has been added. This query finds Android components that return unmodified, received Intents to the calling applications, which -can provide unintended access to internal Content Providers of the victim application. \ No newline at end of file +can provide unintended access to internal content providers of the victim application. \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/android/content-provider/Safe.java b/java/ql/test/library-tests/frameworks/android/content-provider/Safe.java index c61ad642b88..0ef6f8f8e32 100644 --- a/java/ql/test/library-tests/frameworks/android/content-provider/Safe.java +++ b/java/ql/test/library-tests/frameworks/android/content-provider/Safe.java @@ -11,7 +11,7 @@ import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -// This Content Provider isn't exported, so there shouldn't be any flow +// This content provider isn't exported, so there shouldn't be any flow public class Safe extends ContentProvider { void sink(Object o) {} From 58a0bcd70f8279296348ae137652e750c8969b44 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 17 Jan 2022 12:34:37 +0100 Subject: [PATCH 159/196] Apply suggestions from code review Co-authored-by: Chris Smowton --- .../code/java/security/IntentUriPermissionManipulation.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll index 34194e0d074..a2e58ed7ecb 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -72,6 +72,8 @@ private class IntentFlagsOrDataCheckedGuard extends IntentUriPermissionManipulat override predicate checks(Expr e, boolean branch) { exists(MethodAccess ma, Method m | + // This checks `intent` when the result of an `intent.getFlags` or `intent.getData` call flows to `condition` + // (i.e., that result is equality-tested) ma.getMethod() = m and m.getDeclaringType() instanceof TypeIntent and m.hasName(["getFlags", "getData"]) and From 62c21918b2921b444a19c47965a3522f40200993 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 17 Jan 2022 17:39:55 +0100 Subject: [PATCH 160/196] Add QLDoc to guard and sanitizer --- .../IntentUriPermissionManipulation.qll | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll index a2e58ed7ecb..31c9610e3c0 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -38,6 +38,14 @@ private class DefaultIntentUriPermissionManipulationSink extends IntentUriPermis } } +/** + * Sanitizer that prevents access to arbitrary content providers by modifying the Intent in one of + * the following ways: + * * Removing the flags `FLAG_GRANT_READ_URI_PERMISSION` and `FLAG_GRANT_WRITE_URI_PERMISSION`. + * * Setting the flags to a combination that doesn't include `FLAG_GRANT_READ_URI_PERMISSION` or + * `FLAG_GRANT_WRITE_URI_PERMISSION`. + * * Replacing the data URI. + */ private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManipulationSanitizer { IntentFlagsOrDataChangedSanitizer() { exists(MethodAccess ma, Method m | @@ -60,6 +68,20 @@ private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManip } } +/** + * A guard that checks an Intent's flags or data URI to make sure they are trusted. + * It matches the following patterns: + * + * ```java + * if (intent.getData().equals("trustedValue")) {} + * + * if (intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION == 0 && + * intent.getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION == 0) {} + * + * if (intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION != 0 || + * intent.getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION != 0) {} + * ``` + */ private class IntentFlagsOrDataCheckedGuard extends IntentUriPermissionManipulationGuard { Expr condition; From 4e9849e19d0c8536b51bdd70ad14c0d96ce99dde Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Wed, 19 Jan 2022 18:03:00 +0100 Subject: [PATCH 161/196] Refactor IntentFlagsOrDataCheckedGuard to avoid footgun --- .../IntentUriPermissionManipulation.qll | 69 ++++++++++--------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll index 31c9610e3c0..f7c857832a1 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -4,6 +4,7 @@ */ import java +private import semmle.code.java.controlflow.Guards private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.TaintTracking private import semmle.code.java.frameworks.android.Android @@ -85,38 +86,40 @@ private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManip private class IntentFlagsOrDataCheckedGuard extends IntentUriPermissionManipulationGuard { Expr condition; - IntentFlagsOrDataCheckedGuard() { - this.(MethodAccess).getMethod() instanceof EqualsMethod and - condition = [this.(MethodAccess).getArgument(0), this.(MethodAccess).getQualifier()] - or - condition = this.(EqualityTest).getAnOperand().(AndBitwiseExpr) - } + IntentFlagsOrDataCheckedGuard() { intentFlagsOrDataChecked(this, _, _) } - override predicate checks(Expr e, boolean branch) { - exists(MethodAccess ma, Method m | - // This checks `intent` when the result of an `intent.getFlags` or `intent.getData` call flows to `condition` - // (i.e., that result is equality-tested) - ma.getMethod() = m and - m.getDeclaringType() instanceof TypeIntent and - m.hasName(["getFlags", "getData"]) and - TaintTracking::localExprTaint(ma, condition) and - ma.getQualifier() = e - | - bitwiseCheck(branch) - or - this.(MethodAccess).getMethod() instanceof EqualsMethod and branch = true - ) - } - - /** - * Holds if `this` is a bitwise check. `branch` is `true` when the expected value is `0` - * and `false` otherwise. - */ - private predicate bitwiseCheck(boolean branch) { - exists(CompileTimeConstantExpr operand | operand = this.(EqualityTest).getAnOperand() | - if operand.getIntValue() = 0 - then this.(EqualityTest).polarity() = branch - else this.(EqualityTest).polarity().booleanNot() = branch - ) - } + override predicate checks(Expr e, boolean branch) { intentFlagsOrDataChecked(this, e, branch) } +} + +/** + * Holds if `g` checks `intent` when the result of an `intent.getFlags` or `intent.getData` call + * is equality-tested. + */ +private predicate intentFlagsOrDataChecked(Guard g, Expr intent, boolean branch) { + exists(MethodAccess ma, Method m, Expr checkedValue | + ma.getQualifier() = intent and + ma.getMethod() = m and + m.getDeclaringType() instanceof TypeIntent and + m.hasName(["getFlags", "getData"]) and + TaintTracking::localExprTaint(ma, checkedValue) + | + bitwiseCheck(g, branch) and + checkedValue = g.(EqualityTest).getAnOperand().(AndBitwiseExpr) + or + g.(MethodAccess).getMethod() instanceof EqualsMethod and + branch = true and + checkedValue = [g.(MethodAccess).getArgument(0), g.(MethodAccess).getQualifier()] + ) +} + +/** + * Holds if `g` is a bitwise check. `branch` is `true` when the expected value is `0` + * and `false` otherwise. + */ +private predicate bitwiseCheck(Guard g, boolean branch) { + exists(CompileTimeConstantExpr operand | operand = g.(EqualityTest).getAnOperand() | + if operand.getIntValue() = 0 + then g.(EqualityTest).polarity() = branch + else g.(EqualityTest).polarity().booleanNot() = branch + ) } From 265f8a3b19213622443065098573adfcc8f1d4a3 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 20 Jan 2022 13:18:56 +0100 Subject: [PATCH 162/196] Make bitwise taintsteps specific for this query --- .../dataflow/internal/TaintTrackingUtil.qll | 5 --- .../IntentUriPermissionManipulation.qll | 32 +++++++++++++++---- .../IntentUriPermissionManipulationQuery.qll | 4 +++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index 20803508a0d..b1840e56212 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -176,8 +176,6 @@ private predicate localAdditionalTaintExprStep(Expr src, Expr sink) { serializationStep(src, sink) or formatStep(src, sink) - or - bitwiseStep(src, sink) } /** @@ -527,9 +525,6 @@ private class FormatterCallable extends TaintPreservingCallable { } } -/** Holds if taint may flow from the operand of a bitwise expression to its result. */ -private predicate bitwiseStep(Expr src, BitwiseExpr sink) { sink.(BinaryExpr).getAnOperand() = src } - private import StringBuilderVarModule module StringBuilderVarModule { diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll index f7c857832a1..027a915b78b 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -31,6 +31,18 @@ abstract class IntentUriPermissionManipulationSanitizer extends DataFlow::Node { */ abstract class IntentUriPermissionManipulationGuard extends DataFlow::BarrierGuard { } +/** + * An additional taint step for flows related to Intent URI permission manipulation + * vulnerabilities. + */ +class IntentUriPermissionManipulationAdditionalTaintStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a taint + * step for flows related to Intent URI permission manipulation vulnerabilities. + */ + abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); +} + private class DefaultIntentUriPermissionManipulationSink extends IntentUriPermissionManipulationSink { DefaultIntentUriPermissionManipulationSink() { exists(MethodAccess ma | ma.getMethod() instanceof ActivitySetResultMethod | @@ -55,14 +67,11 @@ private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManip this.asExpr() = ma.getQualifier() | m.hasName("removeFlags") and - TaintTracking::localExprTaint(any(GrantReadUriPermissionFlag f).getAnAccess(), - ma.getArgument(0)) and - TaintTracking::localExprTaint(any(GrantWriteUriPermissionFlag f).getAnAccess(), - ma.getArgument(0)) + bitwiseLocalTaintStep*(any(GrantReadUriPermissionFlag f).getAnAccess(), ma.getArgument(0)) and + bitwiseLocalTaintStep*(any(GrantWriteUriPermissionFlag f).getAnAccess(), ma.getArgument(0)) or m.hasName("setFlags") and - not TaintTracking::localExprTaint(any(GrantUriPermissionFlag f).getAnAccess(), - ma.getArgument(0)) + not bitwiseLocalTaintStep*(any(GrantUriPermissionFlag f).getAnAccess(), ma.getArgument(0)) or m.hasName("setData") ) @@ -101,7 +110,7 @@ private predicate intentFlagsOrDataChecked(Guard g, Expr intent, boolean branch) ma.getMethod() = m and m.getDeclaringType() instanceof TypeIntent and m.hasName(["getFlags", "getData"]) and - TaintTracking::localExprTaint(ma, checkedValue) + bitwiseLocalTaintStep*(ma, checkedValue) | bitwiseCheck(g, branch) and checkedValue = g.(EqualityTest).getAnOperand().(AndBitwiseExpr) @@ -123,3 +132,12 @@ private predicate bitwiseCheck(Guard g, boolean branch) { else g.(EqualityTest).polarity().booleanNot() = branch ) } + +/** + * Holds if taint can flow from `source` to `sink` in one local step, + * including bitwise operations. + */ +private predicate bitwiseLocalTaintStep(Expr source, Expr sink) { + TaintTracking::localTaintStep(DataFlow::exprNode(source), DataFlow::exprNode(sink)) or + source = sink.(BinaryExpr).getAnOperand() +} diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll index ab7ff6540ae..067277a71b7 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll @@ -27,4 +27,8 @@ class IntentUriPermissionManipulationConf extends TaintTracking::Configuration { override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { guard instanceof IntentUriPermissionManipulationGuard } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + any(IntentUriPermissionManipulationAdditionalTaintStep c).step(node1, node2) + } } From 3957ebe880138671098e1c3d65d3c9fa5ad4b0c5 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 20 Jan 2022 13:34:32 +0100 Subject: [PATCH 163/196] Fix bitwiseLocalTaintStep --- .../IntentUriPermissionManipulation.qll | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll index 027a915b78b..8a51de7efd7 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -67,11 +67,14 @@ private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManip this.asExpr() = ma.getQualifier() | m.hasName("removeFlags") and - bitwiseLocalTaintStep*(any(GrantReadUriPermissionFlag f).getAnAccess(), ma.getArgument(0)) and - bitwiseLocalTaintStep*(any(GrantWriteUriPermissionFlag f).getAnAccess(), ma.getArgument(0)) + bitwiseLocalTaintStep*(DataFlow::exprNode(any(GrantReadUriPermissionFlag f).getAnAccess()), + DataFlow::exprNode(ma.getArgument(0))) and + bitwiseLocalTaintStep*(DataFlow::exprNode(any(GrantWriteUriPermissionFlag f).getAnAccess()), + DataFlow::exprNode(ma.getArgument(0))) or m.hasName("setFlags") and - not bitwiseLocalTaintStep*(any(GrantUriPermissionFlag f).getAnAccess(), ma.getArgument(0)) + not bitwiseLocalTaintStep*(DataFlow::exprNode(any(GrantUriPermissionFlag f).getAnAccess()), + DataFlow::exprNode(ma.getArgument(0))) or m.hasName("setData") ) @@ -110,7 +113,7 @@ private predicate intentFlagsOrDataChecked(Guard g, Expr intent, boolean branch) ma.getMethod() = m and m.getDeclaringType() instanceof TypeIntent and m.hasName(["getFlags", "getData"]) and - bitwiseLocalTaintStep*(ma, checkedValue) + bitwiseLocalTaintStep*(DataFlow::exprNode(ma), DataFlow::exprNode(checkedValue)) | bitwiseCheck(g, branch) and checkedValue = g.(EqualityTest).getAnOperand().(AndBitwiseExpr) @@ -137,7 +140,7 @@ private predicate bitwiseCheck(Guard g, boolean branch) { * Holds if taint can flow from `source` to `sink` in one local step, * including bitwise operations. */ -private predicate bitwiseLocalTaintStep(Expr source, Expr sink) { - TaintTracking::localTaintStep(DataFlow::exprNode(source), DataFlow::exprNode(sink)) or - source = sink.(BinaryExpr).getAnOperand() +private predicate bitwiseLocalTaintStep(DataFlow::Node source, DataFlow::Node sink) { + TaintTracking::localTaintStep(source, sink) or + source.asExpr() = sink.asExpr().(BitwiseExpr).(BinaryExpr).getAnOperand() } From 62f847a82e08203e3ee53dbc4b7d6b9a8e3a0386 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 20 Jan 2022 13:44:10 +0100 Subject: [PATCH 164/196] Apply suggestions from code review Co-authored-by: Anders Schack-Mulligen --- .../code/java/frameworks/android/OnActivityResultSource.qll | 2 +- .../frameworks/android/sources/OnActivityResultSourceTest.ql | 2 +- 2 files changed, 2 insertions(+), 2 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 6b193074d8e..8eb2aecb4d2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll @@ -46,7 +46,7 @@ class OnActivityResultIncomingIntent extends DataFlow::Node { .getDeclaringType() .hasQualifiedName(["android.app", "android.support.v4.app", "androidx.fragment.app"], "FragmentTransaction") and - any(Argument arg | arg = ma.getAnArgument()).getType() = startingType + ma.getAnArgument().getType() = startingType or ma.getMethod().hasName("show") and ma.getMethod() diff --git a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql index 77821961902..e8c498bebdf 100644 --- a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql +++ b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql @@ -3,7 +3,7 @@ import semmle.code.java.dataflow.FlowSources import TestUtilities.InlineFlowTest class SourceValueFlowConf extends DefaultValueFlowConf { - override predicate isSource(DataFlow::Node sink) { sink instanceof RemoteFlowSource } + override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } } class SourceInlineFlowTest extends InlineFlowTest { From 7167e856fe032bfa31132b5ea9a22eafde2ad62a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 20 Jan 2022 14:07:23 +0100 Subject: [PATCH 165/196] move electron sink to the customizations file --- .../dataflow/ClientSideUrlRedirectCustomizations.qll | 11 +++++++++++ .../security/dataflow/ClientSideUrlRedirectQuery.qll | 10 ---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll index f426dd050c8..1452d60e70a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll @@ -119,6 +119,17 @@ module ClientSideUrlRedirect { } } + /** + * Improper use of openExternal can be leveraged to compromise the user's host. + * When openExternal is used with untrusted content, it can be leveraged to execute arbitrary commands. + */ + class ElectronShellOpenExternalSink extends Sink { + ElectronShellOpenExternalSink() { + this = + DataFlow::moduleMember("electron", "shell").getAMemberCall("openExternal").getArgument(0) + } + } + /** * An expression that may be interpreted as the URL of a script. */ diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll index 3e8825d5dd5..d9566b03313 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll @@ -55,13 +55,3 @@ class Configuration extends TaintTracking::Configuration { guard instanceof HostnameSanitizerGuard } } - -/** - * Improper use of openExternal can be leveraged to compromise the user's host. - * When openExternal is used with untrusted content, it can be leveraged to execute arbitrary commands. - */ -class ElectronShellOpenExternalSink extends Sink { - ElectronShellOpenExternalSink() { - this = DataFlow::moduleMember("electron", "shell").getAMemberCall("openExternal").getArgument(0) - } -} From 43da5aabbe8e21d5e0bdea8dc60459fd35d9edde Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 20 Jan 2022 14:12:33 +0100 Subject: [PATCH 166/196] Java: Add dataflow node encapsulating instance accesses. --- .../code/java/dataflow/internal/DataFlowNodes.qll | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll index e995d19ccaa..3f82183aa65 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll @@ -280,6 +280,21 @@ module Public { explicitInstanceArgument(call, result.asExpr()) or implicitInstanceArgument(call, result.(ImplicitInstanceAccess).getInstanceAccess()) } + + /** A node representing an `InstanceAccessExt`. */ + class InstanceAccessNode extends Node { + InstanceAccessNode() { + this instanceof ImplicitInstanceAccess or this.asExpr() instanceof InstanceAccess + } + + /** Gets the instance access corresponding to this node. */ + InstanceAccessExt getInstanceAccess() { + result = this.(ImplicitInstanceAccess).getInstanceAccess() or result.isExplicit(this.asExpr()) + } + + /** Holds if this is an access to an object's own instance. */ + predicate isOwnInstanceAccess() { this.getInstanceAccess().isOwnInstanceAccess() } + } } private import Public From f53dce3a83de420e0cb2b1098e2d4141b5542972 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 20 Jan 2022 14:20:15 +0100 Subject: [PATCH 167/196] Python: Apply suggestions from code review Co-authored-by: Taus --- python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md | 2 +- .../test/query-tests/Security/CWE-312-CleartextLogging/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 index 0ddb4d804fd..0964101a46f 100644 --- 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 @@ -1,4 +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. +* User names and other account information is no longer considered to be sensitive data for the queries `py/clear-text-logging-sensitive-data` and `py/clear-text-storage-sensitive-data`, since this lead to many false positives. 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 f3dd31543a6..0a3d97426e0 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 @@ -59,7 +59,7 @@ def FPs(account, account_id): # https://github.com/github/codeql/issues/7116 logging.error("Misc Exception. User %s: %s", request.user.username) - # dictionary taint-flow corss-talk + # dictionary taint-flow cross-talk # https://github.com/github/codeql/issues/6380 import settings config = { From 5780161b2c725962d3ab5916150a9b8cb858a8ef Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 20 Jan 2022 15:10:16 +0100 Subject: [PATCH 168/196] fix most issues found by ql/class-doc-style in JS --- .../ql/lib/semmle/javascript/Externs.qll | 6 ++--- .../ql/lib/semmle/javascript/Promises.qll | 4 ++-- .../ql/lib/semmle/javascript/StringOps.qll | 2 +- .../ql/lib/semmle/javascript/TypeScript.qll | 10 ++++----- .../javascript/dataflow/TypeTracking.qll | 4 ++-- .../semmle/javascript/frameworks/Babel.qll | 2 +- .../semmle/javascript/frameworks/Cheerio.qll | 6 ++--- .../javascript/frameworks/ExpressModules.qll | 12 +++++----- .../semmle/javascript/frameworks/Firebase.qll | 2 +- .../lib/semmle/javascript/frameworks/Next.qll | 2 +- .../semmle/javascript/frameworks/Redux.qll | 6 ++--- .../security/dataflow/StoredXssQuery.qll | 2 +- .../UnsafeJQueryPluginCustomizations.qll | 4 ++-- .../Declarations/IneffectiveParameterType.ql | 2 +- .../Expressions/ImplicitOperandConversion.ql | 22 +++++++++---------- .../CWE-915/PrototypePollutingFunction.ql | 8 +++---- .../Security/CWE-094/UntrustedCheckout.ql | 6 ++--- .../experimental/Security/CWE-918/SSRF.qll | 4 ++-- 18 files changed, 52 insertions(+), 52 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/Externs.qll b/javascript/ql/lib/semmle/javascript/Externs.qll index bb723482693..5fe855a46a8 100644 --- a/javascript/ql/lib/semmle/javascript/Externs.qll +++ b/javascript/ql/lib/semmle/javascript/Externs.qll @@ -544,7 +544,7 @@ class ExternalInterface extends ExternalType { } /** - * Externs definition for the Function object. + * The externs definition for the Function object. * * Example: * @@ -561,7 +561,7 @@ class FunctionExternal extends ExternalConstructor { } /** - * Externs definition for the Object object. + * The externs definition for the Object object. * * Example: * @@ -578,7 +578,7 @@ class ObjectExternal extends ExternalConstructor { } /** - * Externs definition for the Array object. + * The externs definition for the Array object. * * Example: * diff --git a/javascript/ql/lib/semmle/javascript/Promises.qll b/javascript/ql/lib/semmle/javascript/Promises.qll index 792cde234ba..d4dce1d01e8 100644 --- a/javascript/ql/lib/semmle/javascript/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/Promises.qll @@ -712,7 +712,7 @@ private module DynamicImportSteps { */ module Promisify { /** - * Gets a call to a `promisifyAll` function. + * A call to a `promisifyAll` function. * E.g. `require("bluebird").promisifyAll(...)`. */ class PromisifyAllCall extends DataFlow::CallNode { @@ -726,7 +726,7 @@ module Promisify { } /** - * Gets a call to a `promisify` function. + * A call to a `promisify` function. * E.g. `require("util").promisify(...)`. */ class PromisifyCall extends DataFlow::CallNode { diff --git a/javascript/ql/lib/semmle/javascript/StringOps.qll b/javascript/ql/lib/semmle/javascript/StringOps.qll index 31190f6cf12..04959341720 100644 --- a/javascript/ql/lib/semmle/javascript/StringOps.qll +++ b/javascript/ql/lib/semmle/javascript/StringOps.qll @@ -512,7 +512,7 @@ module StringOps { } /** - * One of the operands in a string concatenation. + * An operand in a string concatenation. * * Examples: * ``` diff --git a/javascript/ql/lib/semmle/javascript/TypeScript.qll b/javascript/ql/lib/semmle/javascript/TypeScript.qll index 4ba6aed174c..d0e6d351fe1 100644 --- a/javascript/ql/lib/semmle/javascript/TypeScript.qll +++ b/javascript/ql/lib/semmle/javascript/TypeScript.qll @@ -1644,7 +1644,7 @@ class EnumMember extends ASTNode, @enum_member { } /** - * Scope induced by an interface declaration, containing the type parameters declared on the interface. + * A scope induced by an interface declaration, containing the type parameters declared on the interface. * * Interfaces that do not declare type parameters have no scope object. */ @@ -1653,7 +1653,7 @@ class InterfaceScope extends @interface_scope, Scope { } /** - * Scope induced by a type alias declaration, containing the type parameters declared the the alias. + * A scope induced by a type alias declaration, containing the type parameters declared the the alias. * * Type aliases that do not declare type parameters have no scope object. */ @@ -1662,14 +1662,14 @@ class TypeAliasScope extends @type_alias_scope, Scope { } /** - * Scope induced by a mapped type expression, containing the type parameter declared as part of the type. + * A scope induced by a mapped type expression, containing the type parameter declared as part of the type. */ class MappedTypeScope extends @mapped_type_scope, Scope { override string toString() { result = "mapped type scope" } } /** - * Scope induced by an enum declaration, containing the names of its enum members. + * A scope induced by an enum declaration, containing the names of its enum members. * * Initializers of enum members are resolved in this scope since they can reference * previously-defined enum members by their unqualified name. @@ -2637,7 +2637,7 @@ class TypeofType extends Type, @typeof_type { } /** - * One of two values indicating if a signature is a function or constructor signature. + * A value indicating if a signature is a function or constructor signature. */ class SignatureKind extends string { SignatureKind() { this = "function" or this = "constructor" } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll index 0e83d544fd3..f69d25b3a60 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll @@ -15,7 +15,7 @@ private import semmle.javascript.internal.CachedStages private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyName prop) /** - * Summary of the steps needed to track a value to a given dataflow node. + * A summary of the steps needed to track a value to a given dataflow node. * * This can be used to track objects that implement a certain API in order to * recognize calls to that API. Note that type-tracking does not by itself provide a @@ -182,7 +182,7 @@ module TypeTracker { private newtype TTypeBackTracker = MkTypeBackTracker(Boolean hasReturn, OptionalPropertyName prop) /** - * Summary of the steps needed to back-track a use of a value to a given dataflow node. + * A summary of the steps needed to back-track a use of a value to a given dataflow node. * * This can be used to track callbacks that are passed to a certain API call, and are * therefore expected to be called with a certain type of value. diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll index bdacce9142b..05dec2172be 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll @@ -49,7 +49,7 @@ module Babel { } /** - * Configuration object for a Babel plugin. + * A configuration object for a Babel plugin. */ class Plugin extends JSONValue { Config cfg; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll index beffe148ee3..e7a5a282ec4 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll @@ -29,7 +29,7 @@ module Cheerio { DataFlow::SourceNode cheerioRef() { result = cheerioRef(DataFlow::TypeTracker::end()) } /** - * Creation of `cheerio` object, a collection of virtual DOM elements + * A creation of `cheerio` object, a collection of virtual DOM elements * with an interface similar to that of a jQuery object. */ class CheerioObjectCreation extends DataFlow::SourceNode instanceof CheerioObjectCreation::Range { @@ -88,7 +88,7 @@ module Cheerio { } /** - * Definition of a DOM attribute through `cheerio`. + * A definition of a DOM attribute through `cheerio`. */ class AttributeDef extends DOM::AttributeDefinition { DataFlow::CallNode call; @@ -105,7 +105,7 @@ module Cheerio { } /** - * XSS sink through `cheerio`. + * An XSS sink through `cheerio`. */ class XssSink extends Xss::DomBasedXss::Sink { XssSink() { diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll b/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll index 3cc75f73afb..64b4122fb46 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll @@ -16,7 +16,7 @@ module ExpressLibraries { } /** - * Header produced by a route handler of the "x-frame-options" module. + * A header produced by a route handler of the "x-frame-options" module. */ class XFrameOptionsRouteHandlerHeader extends HTTP::ImplicitHeaderDefinition { XFrameOptionsRouteHandlerHeader() { this instanceof XFrameOptionsRouteHandler } @@ -29,7 +29,7 @@ module ExpressLibraries { } /** - * Route handler from the "x-frame-options" module. + * A route handler from the "x-frame-options" module. */ class XFrameOptionsRouteHandler extends HTTP::RouteHandler { XFrameOptionsRouteHandler() { @@ -43,7 +43,7 @@ module ExpressLibraries { } /** - * Header produced by a route handler of the "frameguard" module. + * A header produced by a route handler of the "frameguard" module. */ class FrameGuardRouteHandlerHeader extends HTTP::ImplicitHeaderDefinition { FrameGuardRouteHandlerHeader() { this instanceof FrameGuardRouteHandler } @@ -56,7 +56,7 @@ module ExpressLibraries { } /** - * Route handler from the "frameguard" module. + * A route handler from the "frameguard" module. */ class FrameGuardRouteHandler extends HTTP::RouteHandler { FrameGuardRouteHandler() { this = DataFlow::moduleImport("frameguard").getAnInvocation() } @@ -68,7 +68,7 @@ module ExpressLibraries { } /** - * Header produced by a route handler of the "helmet" module. + * A header produced by a route handler of the "helmet" module. */ class HelmetRouteHandlerHeader extends HTTP::ImplicitHeaderDefinition { HelmetRouteHandlerHeader() { this instanceof HelmetRouteHandler } @@ -81,7 +81,7 @@ module ExpressLibraries { } /** - * Route handler from the "helmet" module. + * A route handler from the "helmet" module. */ class HelmetRouteHandler extends HTTP::RouteHandler { HelmetRouteHandler() { diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll b/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll index fc920a34725..3678d5fde57 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll @@ -179,7 +179,7 @@ module Firebase { /** Gets a data flow node holding a `RefBuilder` object. */ DataFlow::SourceNode ref() { result = refBuilder(DataFlow::TypeTracker::end()) } - /** Gets a call that registers a listener on a `RefBuilder`, such as `ref.onCreate(...)`. */ + /** A call that registers a listener on a `RefBuilder`, such as `ref.onCreate(...)`. */ class RefBuilderListenCall extends DataFlow::MethodCallNode { RefBuilderListenCall() { this = ref().getAMethodCall() and diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll index 65f898f0a0a..1e0c96b1d8d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll @@ -44,7 +44,7 @@ module NextJS { } /** - * User defined path parameter in `Next.js`. + * A user defined path parameter in `Next.js`. */ class NextParams extends RemoteFlowSource { NextParams() { diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll index 3ee60691731..375fcefac2e 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll @@ -54,7 +54,7 @@ module Redux { } /** - * Creation of a redux store, usually via a call to `createStore`. + * A creation of a redux store, usually via a call to `createStore`. */ class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range { /** Gets a reference to the store. */ @@ -566,7 +566,7 @@ module Redux { } /** - * One of the action creators made by a call to `createActions`: + * An action creator made by a call to `createActions`: * ```js * let { actionOne, actionTwo } = createActions({ * ACTION_ONE: (x, y) => { x, y }, @@ -988,7 +988,7 @@ module Redux { API::Node useSelector() { result = API::moduleImport("react-redux").getMember("useSelector") } /** - * Step out of a `useSelector` call, such as from `state.x` to the result of `useSelector(state => state.x)`. + * A step out of a `useSelector` call, such as from `state.x` to the result of `useSelector(state => state.x)`. */ class UseSelectorStep extends StateStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssQuery.qll index 654b609a23a..e03c85b7330 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssQuery.qll @@ -31,7 +31,7 @@ class FileNameSourceAsSource extends Source { FileNameSourceAsSource() { this instanceof FileNameSource } } -/** User-controlled torrent information, considered as a flow source for stored XSS. */ +/** An instance of user-controlled torrent information, considered as a flow source for stored XSS. */ class UserControlledTorrentInfoAsSource extends Source { UserControlledTorrentInfoAsSource() { this instanceof ParseTorrent::UserControlledTorrentInfo } } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll index 94d0492c93e..fe16e66737a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -100,7 +100,7 @@ module UnsafeJQueryPlugin { } /** - * Expression of form `isElement(x)`, which sanitizes `x`. + * An expression of form `isElement(x)`, which sanitizes `x`. */ class IsElementSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode { IsElementSanitizer() { @@ -116,7 +116,7 @@ module UnsafeJQueryPlugin { } /** - * Expression like `typeof x. !== "undefined"` or `x.`, which sanitizes `x`, as it is unlikely to be a string afterwards. + * An expression like `typeof x. !== "undefined"` or `x.`, which sanitizes `x`, as it is unlikely to be a string afterwards. */ class PropertyPresenceSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { DataFlow::Node input; diff --git a/javascript/ql/src/Declarations/IneffectiveParameterType.ql b/javascript/ql/src/Declarations/IneffectiveParameterType.ql index 8e4eb82bcf8..4dd8837a661 100644 --- a/javascript/ql/src/Declarations/IneffectiveParameterType.ql +++ b/javascript/ql/src/Declarations/IneffectiveParameterType.ql @@ -22,7 +22,7 @@ predicate isCommonPredefinedTypeName(string name) { } /** - * Any local type declaration, excluding imported names that are not explicitly used as types. + * A local type declaration, excluding imported names that are not explicitly used as types. */ class DefiniteTypeDecl extends TypeDecl { DefiniteTypeDecl() { diff --git a/javascript/ql/src/Expressions/ImplicitOperandConversion.ql b/javascript/ql/src/Expressions/ImplicitOperandConversion.ql index f870c4b7cae..5d3f16e0eb8 100644 --- a/javascript/ql/src/Expressions/ImplicitOperandConversion.ql +++ b/javascript/ql/src/Expressions/ImplicitOperandConversion.ql @@ -56,8 +56,8 @@ abstract class ImplicitConversionWithWhitelist extends ImplicitConversion { } /** - * Property names in `in` expressions are converted to strings, - * so they should be strings or numbers. + * A property name in an `in` expression that is converted to string, + * so it should be a string or number. */ class PropertyNameConversion extends ImplicitConversionWithWhitelist { PropertyNameConversion() { this.asExpr() = parent.(InExpr).getLeftOperand() } @@ -68,8 +68,8 @@ class PropertyNameConversion extends ImplicitConversionWithWhitelist { } /** - * Property names in index expressions are converted to strings, - * so they should be Booleans, strings or numbers. + * A property name in an index expression that is converted to string, + * so it should be Boolean, string or number. */ class IndexExprConversion extends ImplicitConversionWithWhitelist { IndexExprConversion() { this.asExpr() = parent.(IndexExpr).getIndex() } @@ -82,7 +82,7 @@ class IndexExprConversion extends ImplicitConversionWithWhitelist { } /** - * Expressions that are interpreted as objects shouldn't be primitive values. + * An expression that is interpreted as an object, and therefore shouldn't be a primitive value. */ class ObjectConversion extends ImplicitConversionWithWhitelist { ObjectConversion() { @@ -107,8 +107,8 @@ class ConstructorConversion extends ImplicitConversionWithWhitelist { } /** - * Operands of relational operators are converted to strings or numbers, - * and hence should be strings, numbers or Dates. + * An operand of an relational comparison that is converted to string or number, + * and hence should be a string, number or Date. */ class RelationalOperandConversion extends ImplicitConversionWithWhitelist { RelationalOperandConversion() { parent instanceof RelationalComparison } @@ -121,8 +121,8 @@ class RelationalOperandConversion extends ImplicitConversionWithWhitelist { } /** - * Operands of arithmetic and bitwise operations are converted to numbers, - * so they should be Booleans, numbers or Dates. + * An operand of arithmetic and bitwise operations that is converted to a number, + * so it should be a Boolean, number or Date. */ class NumericConversion extends ImplicitConversion { NumericConversion() { @@ -156,7 +156,7 @@ abstract class NullOrUndefinedConversion extends ImplicitConversion { } /** - * Operands of `+` or `+=` are converted to strings or numbers, and hence + * An operand of `+` or `+=` that is converted to string or number, and hence * should not be `null` or `undefined`. */ class PlusConversion extends NullOrUndefinedConversion { @@ -186,7 +186,7 @@ class PlusConversion extends NullOrUndefinedConversion { } /** - * Template literal elements are converted to strings, and hence should not + * A template literal element that is converted to a string, and hence should not * be `null` or `undefined`. */ class TemplateElementConversion extends NullOrUndefinedConversion { diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql index f3143d1cf06..f6d0ed38fa2 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql @@ -193,7 +193,7 @@ string unsafePropName() { } /** - * Flow label representing an unsafe property name, or an object obtained + * A flow label representing an unsafe property name, or an object obtained * by using such a property in a dynamic read. */ class UnsafePropLabel extends FlowLabel { @@ -295,7 +295,7 @@ class PropNameTracking extends DataFlow::Configuration { } /** - * Sanitizer guard of form `x === "__proto__"` or `x === "constructor"`. + * A sanitizer guard of form `x === "__proto__"` or `x === "constructor"`. */ class DenyListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { override EqualityTest astNode; @@ -355,7 +355,7 @@ class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode, CallNode { } /** - * Sanitizer guard for `key in dst`. + * A sanitizer guard for `key in dst`. * * Since `"__proto__" in obj` and `"constructor" in obj` is true for most objects, * this is seen as a sanitizer for `key` in the false outcome. @@ -374,7 +374,7 @@ class InExprGuard extends DataFlow::BarrierGuardNode, DataFlow::ValueNode { } /** - * Sanitizer guard for `instanceof` expressions. + * A sanitizer guard for `instanceof` expressions. * * `Object.prototype instanceof X` is never true, so this blocks the `__proto__` label. * diff --git a/javascript/ql/src/experimental/Security/CWE-094/UntrustedCheckout.ql b/javascript/ql/src/experimental/Security/CWE-094/UntrustedCheckout.ql index 5227d433088..2715f788e5c 100644 --- a/javascript/ql/src/experimental/Security/CWE-094/UntrustedCheckout.ql +++ b/javascript/ql/src/experimental/Security/CWE-094/UntrustedCheckout.ql @@ -16,7 +16,7 @@ import javascript import experimental.semmle.javascript.Actions /** - * Action step that doesn't contain `actor` or `label` check in `if:` or + * An action step that doesn't contain `actor` or `label` check in `if:` or * the check requires manual analysis. */ class ProbableStep extends Actions::Step { @@ -46,7 +46,7 @@ class ProbableStep extends Actions::Step { } /** - * Action job that doesn't contain `actor` or `label` check in `if:` or + * An action job that doesn't contain `actor` or `label` check in `if:` or * the check requires manual analysis. */ class ProbableJob extends Actions::Job { @@ -76,7 +76,7 @@ class ProbableJob extends Actions::Job { } /** - * Action step that doesn't contain `actor` or `label` check in `if:` or + * An action step that doesn't contain `actor` or `label` check in `if:` or */ class ProbablePullRequestTarget extends Actions::On, Actions::MappingOrSequenceOrScalar { ProbablePullRequestTarget() { diff --git a/javascript/ql/src/experimental/Security/CWE-918/SSRF.qll b/javascript/ql/src/experimental/Security/CWE-918/SSRF.qll index 3826a42fc1d..cc582534e23 100644 --- a/javascript/ql/src/experimental/Security/CWE-918/SSRF.qll +++ b/javascript/ql/src/experimental/Security/CWE-918/SSRF.qll @@ -119,7 +119,7 @@ class TernaryOperatorSanitizerGuard extends TaintTracking::SanitizerGuardNode { } /** - * Number.isInteger is a sanitizer guard because a number can't be used to exploit a SSRF. + * A call to Number.isInteger seen as a sanitizer guard because a number can't be used to exploit a SSRF. */ class IntegerCheck extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode { IntegerCheck() { this = DataFlow::globalVarRef("Number").getAMemberCall("isInteger") } @@ -131,7 +131,7 @@ class IntegerCheck extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode } /** - * ValidatorCheck identifies if exists a call to validator's library methods. + * A call to validator's library methods. * validator is a library which has a variety of input-validation functions. We are interesed in * checking that source is a number (any type of number) or an alphanumeric value. */ From 3155114e365f60e6672a12cb7e764b4530e7ec2d Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 20 Jan 2022 14:35:59 +0100 Subject: [PATCH 169/196] use more set literals --- javascript/ql/lib/semmle/javascript/DOM.qll | 9 ++------- javascript/ql/lib/semmle/javascript/Extend.qll | 7 +------ javascript/ql/lib/semmle/javascript/Promises.qll | 9 ++------- .../semmle/javascript/dataflow/TaintTracking.qll | 12 +++++------- .../lib/semmle/javascript/frameworks/Cheerio.qll | 4 ++-- .../frameworks/ConnectExpressShared.qll | 9 +++++---- .../ql/lib/semmle/javascript/frameworks/Files.qll | 2 +- .../ql/lib/semmle/javascript/frameworks/NoSQL.qll | 5 +---- .../semmle/javascript/frameworks/NodeJSLib.qll | 7 +------ .../lib/semmle/javascript/frameworks/PkgCloud.qll | 14 ++------------ .../lib/semmle/javascript/frameworks/Restify.qll | 15 +++++---------- .../lib/semmle/javascript/frameworks/SocketIO.qll | 11 ++--------- .../lib/semmle/javascript/frameworks/jQuery.qll | 7 +------ .../security/dataflow/IndirectCommandArgument.qll | 6 +++--- .../dataflow/PrototypePollutionCustomizations.qll | 10 +--------- .../tutorials/Validating RAML-based APIs/HTTP.qll | 7 +------ .../Validating RAML-based APIs/query2.ql | 7 +------ .../Validating RAML-based APIs/query3.ql | 7 +------ .../Validating RAML-based APIs/query4.ql | 7 +------ 19 files changed, 38 insertions(+), 117 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/DOM.qll b/javascript/ql/lib/semmle/javascript/DOM.qll index 40b2f42822d..278cd0f7d31 100644 --- a/javascript/ql/lib/semmle/javascript/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/DOM.qll @@ -176,18 +176,13 @@ module DOM { eltName = ["script", "iframe", "embed", "video", "audio", "source", "track"] and attrName = "src" or - ( - eltName = "link" or - eltName = "a" or - eltName = "base" or - eltName = "area" - ) and + eltName = ["link", "a", "base", "area"] and attrName = "href" or eltName = "form" and attrName = "action" or - (eltName = "input" or eltName = "button") and + eltName = ["input", "button"] and attrName = "formaction" ) } diff --git a/javascript/ql/lib/semmle/javascript/Extend.qll b/javascript/ql/lib/semmle/javascript/Extend.qll index 30bcf82658c..cde984d55ae 100644 --- a/javascript/ql/lib/semmle/javascript/Extend.qll +++ b/javascript/ql/lib/semmle/javascript/Extend.qll @@ -47,12 +47,7 @@ private DataFlow::SourceNode localDollar() { */ private class ExtendCallWithFlag extends ExtendCall { ExtendCallWithFlag() { - exists(string name | this = DataFlow::moduleImport(name).getACall() | - name = "extend" or - name = "extend2" or - name = "just-extend" or - name = "node.extend" - ) + this = DataFlow::moduleImport(["extend", "extend2", "just-extend", "node.extend"]).getACall() or this = localDollar().getAMemberCall("extend") } diff --git a/javascript/ql/lib/semmle/javascript/Promises.qll b/javascript/ql/lib/semmle/javascript/Promises.qll index 792cde234ba..a80507d2b0c 100644 --- a/javascript/ql/lib/semmle/javascript/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/Promises.qll @@ -157,9 +157,7 @@ class ResolvedES2015PromiseDefinition extends ResolvedPromiseDefinition { */ class AggregateES2015PromiseDefinition extends PromiseCreationCall { AggregateES2015PromiseDefinition() { - exists(string m | m = "all" or m = "race" or m = "any" or m = "allSettled" | - this = getAPromiseObject().getAMemberCall(m) - ) + this = getAPromiseObject().getAMemberCall(["all", "race", "any", "allSettled"]) or this = DataFlow::moduleImport("promise.allsettled").getACall() } @@ -654,10 +652,7 @@ private module ClosurePromise { succ = call and pred = call.getAnArgument() | - name = "all" or - name = "allSettled" or - name = "firstFulfilled" or - name = "race" + name = ["all", "allSettled", "firstFulfilled", "race"] ) or // promise created through goog.promise.withResolver() diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index c8c2fcc35c6..a2a38b47c8b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -694,15 +694,13 @@ module TaintTracking { ) or // `(encode|decode)URI(Component)?` propagate taint - exists(DataFlow::CallNode c, string name | + exists(DataFlow::CallNode c | succ = c and - c = DataFlow::globalVarRef(name).getACall() and + c = + DataFlow::globalVarRef([ + "encodeURI", "decodeURI", "encodeURIComponent", "decodeURIComponent" + ]).getACall() and pred = c.getArgument(0) - | - name = "encodeURI" or - name = "decodeURI" or - name = "encodeURIComponent" or - name = "decodeURIComponent" ) or // In and out of .replace callbacks diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll index beffe148ee3..61ee507d44e 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll @@ -64,10 +64,10 @@ module Cheerio { call = cheerioObjectRef().getAMethodCall(name) and result = call | - if name = "attr" or name = "data" or name = "prop" or name = "css" + if name = ["attr", "data", "prop", "css"] then call.getNumArgument() = 2 else - if name = "val" or name = "html" or name = "text" + if name = ["val", "html", "text"] then call.getNumArgument() = 1 else ( name != "toString" and diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll b/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll index 28283d90b92..9da7c959cb0 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll @@ -17,10 +17,11 @@ module ConnectExpressShared { */ private class RouteHandlerSignature extends string { RouteHandlerSignature() { - this = "request,response" or - this = "request,response,next" or - this = "request,response,next,parameter" or - this = "error,request,response,next" + this = + [ + "request,response", "request,response,next", "request,response,next,parameter", + "error,request,response,next" + ] } /** Gets the index of the parameter corresonding to the given `kind`, if any. */ diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll index 13ed0c679ae..6f304cfef8a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll @@ -159,7 +159,7 @@ private module FStream { or readOrWrite = "Writer" and writer = true ) and - (subMod = "File" or subMod = "Dir" or subMod = "Link" or subMod = "Proxy") + subMod = ["File", "Dir", "Link", "Proxy"] | result = mod.getAPropertyRead(readOrWrite) or result = mod.getAPropertyRead(readOrWrite).getAPropertyRead(subMod) or diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll index 8924bcdd46d..11c0b6691b1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll @@ -485,10 +485,7 @@ private module Mongoose { * Holds if Document method `name` returns a Document. */ predicate returnsDocument(string name) { - name = "depopulate" or - name = "init" or - name = "populate" or - name = "overwrite" + name = ["depopulate", "init", "populate", "overwrite"] } } } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll index f03c4c32975..31c42b48bca 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll @@ -548,12 +548,7 @@ module NodeJSLib { /** A file system read. */ private class NodeJSFileSystemAccessRead extends FileSystemReadAccess, NodeJSFileSystemAccess { - NodeJSFileSystemAccessRead() { - methodName = "read" or - methodName = "readSync" or - methodName = "readFile" or - methodName = "readFileSync" - } + NodeJSFileSystemAccessRead() { methodName = ["read", "readSync", "readFile", "readFileSync"] } override DataFlow::Node getADataNode() { if methodName.matches("%Sync") diff --git a/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll b/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll index a619dedcad9..ef1e5b9bdbb 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll @@ -55,20 +55,10 @@ module PkgCloud { */ kind = "user name" and - ( - propertyName = "account" or - propertyName = "keyId" or - propertyName = "storageAccount" or - propertyName = "username" - ) + propertyName = ["account", "keyId", "storageAccount", "username"] or kind = "password" and - ( - propertyName = "key" or - propertyName = "apiKey" or - propertyName = "storageAccessKey" or - propertyName = "password" - ) + propertyName = ["key", "apiKey", "storageAccessKey", "password"] or kind = "token" and propertyName = "token" diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll index 0cd6cbcf436..f83f2930f51 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll @@ -106,16 +106,11 @@ module Restify { methodName = "getPath" ) or - exists(string methodName | - // `request.getContentType()`, `request.userAgent()`, `request.trailer(...)`, `request.header(...)` - kind = "header" and - this.asExpr().(MethodCallExpr).calls(request, methodName) - | - methodName = "getContentType" or - methodName = "userAgent" or - methodName = "trailer" or - methodName = "header" - ) + // `request.getContentType()`, `request.userAgent()`, `request.trailer(...)`, `request.header(...)` + kind = "header" and + this.asExpr() + .(MethodCallExpr) + .calls(request, ["getContentType", "userAgent", "trailer", "header"]) or // `req.cookies kind = "cookie" and diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll index 28ecf41781e..f91bd7c5a25 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll @@ -227,15 +227,8 @@ module SocketIO { ) or // invocation of a chainable getter method - exists(string m | - m = "broadcast" or - m = "json" or - m = "local" or - m = "volatile" - | - result = pred.getAPropertyRead(m) and - t = t2.continue() - ) + result = pred.getAPropertyRead(["broadcast", "json", "local", "volatile"]) and + t = t2.continue() ) } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll index 46cee36f628..faa10407f86 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll @@ -385,12 +385,7 @@ private module JQueryClientRequest { string name; JQueryAjaxShortHand() { - ( - name = "get" or - name = "getJSON" or - name = "getScript" or - name = "post" - ) and + name = ["get", "getJSON", "getScript", "post"] and this = jquery().getAMemberCall(name) or name = "load" and diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll index 752e7cf0246..6d6c9c3d75f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll @@ -12,13 +12,13 @@ import javascript */ private predicate shellCmd(Expr shell, string arg) { exists(string s | s = shell.getStringValue() | - (s = "sh" or s = "bash" or s = "/bin/sh" or s = "/bin/bash") and + s = ["sh", "bash", "/bin/sh", "/bin/bash"] and arg = "-c" ) or exists(string s | s = shell.getStringValue().toLowerCase() | - (s = "cmd" or s = "cmd.exe") and - (arg = "/c" or arg = "/C") + s = ["cmd", "cmd.exe"] and + arg = ["/c", "/C"] ) } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll index 40a5202a815..a9b3c3e3282 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll @@ -179,15 +179,7 @@ module PrototypePollution { call = DataFlow::moduleImport(id).getACall() or call = DataFlow::moduleImport(id).getAMemberCall(_) ) and - ( - id = "deep" - or - id = "extend2" - or - id = "js-extend" - or - id = "smart-extend" - ) + id = ["deep", "extend2", "js-extend", "smart-extend"] or call.isDeep() and call = AngularJS::angular().getAMemberCall("merge") and diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/HTTP.qll b/javascript/ql/test/tutorials/Validating RAML-based APIs/HTTP.qll index e4a45a5f5f0..970d420af59 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/HTTP.qll +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/HTTP.qll @@ -1,9 +1,4 @@ /** * Some commonly used HTTP verbs. */ -string httpVerb() { - result = "get" or - result = "put" or - result = "post" or - result = "delete" -} +string httpVerb() { result = ["get", "put", "post", "delete"] } diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.ql b/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.ql index d3617e1f759..5e5acba3d3e 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.ql +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.ql @@ -1,11 +1,6 @@ import javascript -string httpVerb() { - result = "get" or - result = "put" or - result = "post" or - result = "delete" -} +string httpVerb() { result = ["get", "put", "post", "delete"] } /** A RAML specification. */ class RAMLSpec extends YAMLDocument, YAMLMapping { diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.ql b/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.ql index 2a42c0f107e..a503976c388 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.ql +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.ql @@ -1,11 +1,6 @@ import javascript -string httpVerb() { - result = "get" or - result = "put" or - result = "post" or - result = "delete" -} +string httpVerb() { result = ["get", "put", "post", "delete"] } /** A RAML specification. */ class RAMLSpec extends YAMLDocument, YAMLMapping { diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.ql b/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.ql index 04dd9b9bd4c..1bbd4b07622 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.ql +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.ql @@ -1,11 +1,6 @@ import javascript -string httpVerb() { - result = "get" or - result = "put" or - result = "post" or - result = "delete" -} +string httpVerb() { result = ["get", "put", "post", "delete"] } /** A RAML specification. */ class RAMLSpec extends YAMLDocument, YAMLMapping { From 2bffe56580aac8db70a196577e827f764f00762b Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 20 Jan 2022 16:06:57 +0100 Subject: [PATCH 170/196] update expected output --- .../test/tutorials/Validating RAML-based APIs/query2.expected | 4 ++-- .../test/tutorials/Validating RAML-based APIs/query3.expected | 2 +- .../test/tutorials/Validating RAML-based APIs/query4.expected | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.expected b/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.expected index 9291ac9ec96..a3c1a3dcb2b 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.expected +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.expected @@ -1,5 +1,5 @@ -WARNING: Unused method getMethod (query2.ql:36,14-23) -WARNING: Unused method getResponse (query2.ql:50,13-24) +WARNING: Unused method getMethod (query2.ql:31,14-23) +WARNING: Unused method getResponse (query2.ql:45,13-24) | robonode/src/assets/raml/api.raml:8:3:72:14 | get: | /robots | | robonode/src/assets/raml/api.raml:15:5:72:14 | uriParameters: | /robots/{robotId} | | robonode/src/assets/raml/api.raml:24:7:54:4 | get: | /robots/{robotId}/commands | diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.expected b/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.expected index 712ea9d5cb9..cbd41e84437 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.expected +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.expected @@ -1,2 +1,2 @@ -WARNING: Unused method getMethod (query3.ql:36,14-23) +WARNING: Unused method getMethod (query3.ql:31,14-23) | 1 | diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.expected b/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.expected index 54cb9f6cb8e..f79ca3f1098 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.expected +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.expected @@ -1,5 +1,5 @@ -WARNING: Unused method getMethod (query4.ql:36,14-23) -WARNING: Unused method getResponse (query4.ql:50,13-24) +WARNING: Unused method getMethod (query4.ql:31,14-23) +WARNING: Unused method getResponse (query4.ql:45,13-24) | robonode/src/assets/raml/api.raml:9:5:14:2 | description: \| | | robonode/src/assets/raml/api.raml:25:9:29:6 | description: \| | | robonode/src/assets/raml/api.raml:30:9:54:4 | description: \| | From 6fe0b789782f24955677074d304c6beba90c4cc7 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Thu, 20 Jan 2022 14:39:55 +0100 Subject: [PATCH 171/196] Remove PendingIntentAsField step and add SliceProviderLifecycle step --- .../code/java/frameworks/android/Slice.qll | 30 +++++++++++++++++++ .../java/security/ImplicitPendingIntents.qll | 16 +--------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll b/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll index ac688503e6d..5538dbd4163 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll @@ -5,6 +5,36 @@ private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.FlowSteps private import semmle.code.java.dataflow.ExternalFlow +/** The class `androidx.slice.SliceProvider`. */ +class SliceProvider extends Class { + SliceProvider() { this.hasQualifiedName("androidx.slice", "SliceProvider") } +} + +/** + * An additional value step for modeling the lifecycle of a `SliceProvider`. + * It connects the `PostUpdateNode` of any update done to the provider object in + * `onCreateSliceProvider` to the instance parameter of `onBindSlice`. + */ +private class SliceProviderLifecycleStep extends AdditionalValueStep { + override predicate step(DataFlow::Node node1, DataFlow::Node node2) { + exists(Method onCreate, Method onBind, RefType declaringClass | + declaringClass.getASupertype*() instanceof SliceProvider and + onCreate.getDeclaringType() = declaringClass and + onCreate.hasName("onCreateSliceProvider") and + onBind.getDeclaringType() = declaringClass and + onBind.hasName("onBindSlice") + | + node1 + .(DataFlow::PostUpdateNode) + .getPreUpdateNode() + .(DataFlow::InstanceAccessNode) + .isOwnInstanceAccess() and + node1.getEnclosingCallable() = onCreate and + node2.(DataFlow::InstanceParameterNode).getEnclosingCallable() = onBind + ) + } +} + private class SliceActionsInheritTaint extends DataFlow::SyntheticFieldContent, TaintInheritingContent { SliceActionsInheritTaint() { this.getField().matches("androidx.slice.Slice.action") } diff --git a/java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll b/java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll index a325a5fd9b3..31f9e886e81 100644 --- a/java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll +++ b/java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll @@ -68,21 +68,7 @@ private class SendPendingIntent extends ImplicitPendingIntentSink { override predicate hasState(DataFlow::FlowState state) { state = "MutablePendingIntent" } } -/** - * Propagates taint from any tainted object to reads from its `PendingIntent`-typed fields. - */ -private class PendingIntentAsFieldAdditionalTaintStep extends ImplicitPendingIntentAdditionalTaintStep { - override predicate step(DataFlow::Node node1, DataFlow::Node node2) { - exists(Field f | - f.getType() instanceof PendingIntent and - node1.(DataFlow::PostUpdateNode).getPreUpdateNode() = - DataFlow::getFieldQualifier(f.getAnAccess().(FieldWrite)) and - node2.asExpr().(FieldRead).getField() = f - ) - } -} - -private class MutablePendingIntentFlowStep extends PendingIntentAsFieldAdditionalTaintStep { +private class MutablePendingIntentFlowStep extends ImplicitPendingIntentAdditionalTaintStep { override predicate step( DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, DataFlow::FlowState state2 From e689f6bad2ab69ca00a3ad9acc267763b212f2da Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 20 Jan 2022 17:30:14 +0000 Subject: [PATCH 172/196] C++: Use the IR for 'cpp/return-stack-allocated-memory'. --- .../ReturnStackAllocatedMemory.cpp | 2 +- .../ReturnStackAllocatedMemory.ql | 186 ++++++++++---- .../ReturnStackAllocatedMemory.expected | 239 +++++++++++++++++- .../ReturnStackAllocatedMemory/test.cpp | 12 +- 4 files changed, 377 insertions(+), 62 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp index 00dfa215b33..bf9822d5fd8 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp @@ -4,4 +4,4 @@ Record* fixRecord(Record* r) { myRecord.fix(); return &myRecord; //returns reference to myRecord, which is a stack-allocated object -} +} \ No newline at end of file diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql index f5dda53d484..b136e511526 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql @@ -3,7 +3,7 @@ * @description A function returns a pointer to a stack-allocated region of * memory. This memory is deallocated at the end of the function, * which may lead the caller to dereference a dangling pointer. - * @kind problem + * @kind path-problem * @id cpp/return-stack-allocated-memory * @problem.severity warning * @precision high @@ -12,59 +12,151 @@ */ import cpp -import semmle.code.cpp.dataflow.EscapesTree -import semmle.code.cpp.models.interfaces.PointerWrapper -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.IR +import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow /** - * Holds if `n1` may flow to `n2`, ignoring flow through fields because these - * are currently modeled as an overapproximation that assumes all objects may - * alias. + * Holds if `source` is a node that represents the use of a stack variable */ -predicate conservativeDataFlowStep(DataFlow::Node n1, DataFlow::Node n2) { - DataFlow::localFlowStep(n1, n2) and - not n2.asExpr() instanceof FieldAccess and - not hasNontrivialConversion(n2.asExpr()) -} - -/** - * Holds if `e` has a conversion that changes it from lvalue to pointer or - * back. As the data-flow library does not support conversions, we cannot track - * data flow through such expressions. - */ -predicate hasNontrivialConversion(Expr e) { - e instanceof Conversion and - not ( - e instanceof Cast - or - e instanceof ParenthesisExpr +predicate isSource(Node source) { + exists(VariableAddressInstruction var | + var = source.asInstruction() and + var.getASTVariable() instanceof StackVariable and + // Pointer-to-member types aren't properly handled in the dbscheme. + not var.getResultType() instanceof PointerToMemberType and + // Rule out FPs caused by extraction errors. + not any(ErrorExpr e).getEnclosingFunction() = var.getEnclosingFunction() ) - or - // A smart pointer can be stack-allocated while the data it points to is heap-allocated. - // So we exclude such "conversions" from this predicate. - e = any(PointerWrapper wrapper).getAnUnwrapperFunction().getACallToThisFunction() - or - hasNontrivialConversion(e.getConversion()) } -from StackVariable var, VariableAccess va, ReturnStmt r -where - not var.getUnspecifiedType() instanceof ReferenceType and - not r.isFromUninstantiatedTemplate(_) and - va = var.getAnAccess() and +/** + * Holds if `sink` is a node that represents the `StoreInstruction` that is subsequently used in + * a `ReturnValueInstruction`. We use the `StoreInstruction` instead of the instruction that defines the + * `ReturnValueInstruction`'s source value oprand because the former has better location information. + */ +predicate isSink(Node sink) { + exists(StoreInstruction store | + store.getDestinationAddress().(VariableAddressInstruction).getIRVariable() instanceof + IRReturnVariable and + sink.asOperand() = store.getSourceValueOperand() + ) +} + +/** Holds if `node1` _must_ flow to `node2`. */ +predicate step(Node node1, Node node2) { + instructionToOperandStep(node1.asInstruction(), node2.asOperand()) + or + operandToInstructionStep(node1.asOperand(), node2.asInstruction()) +} + +predicate instructionToOperandStep(Instruction instr, Operand operand) { operand.getDef() = instr } + +/** + * Holds if `operand` flows to the result of `instr`. + * + * This predicate ignores flow through `PhiInstruction`s to create a 'must flow' relation. It also + * intentionally conflates addresses of fields and their object, and pointer offsets with their + * base pointer as this allows us to detect cases where an object's address flows to a return statement + * via a field. For example: + * + * ```cpp + * struct S { int x, y }; + * int* test() { + * S s; + * return &s.x; // BAD: &s.x is an address of a variable on the stack. + * } + * ``` + */ +predicate operandToInstructionStep(Operand operand, Instruction instr) { + instr.(CopyInstruction).getSourceValueOperand() = operand + or + instr.(ConvertInstruction).getUnaryOperand() = operand + or + instr.(CheckedConvertOrNullInstruction).getUnaryOperand() = operand + or + instr.(InheritanceConversionInstruction).getUnaryOperand() = operand + or + instr.(FieldAddressInstruction).getObjectAddressOperand() = operand + or + instr.(PointerOffsetInstruction).getLeftOperand() = operand +} + +/** Holds if a source node flows to `n`. */ +predicate branchlessLocalFlow0(Node n) { + isSource(n) + or + exists(Node mid | + branchlessLocalFlow0(mid) and + step(mid, n) + ) +} + +/** Holds if `n` is reachable through some source node, and `n` also eventually reaches a sink. */ +predicate branchlessLocalFlow1(Node n) { + branchlessLocalFlow0(n) and ( - // To check if the address escapes directly from `e` in `return e`, we need - // to check the fully-converted `e` in case there are implicit - // array-to-pointer conversions or reference conversions. - variableAddressEscapesTree(va, r.getExpr().getFullyConverted()) + isSink(n) or - // The data flow library doesn't support conversions, so here we check that - // the address escapes into some expression `pointerToLocal`, which flows - // in one or more steps to a returned expression. - exists(Expr pointerToLocal | - variableAddressEscapesTree(va, pointerToLocal.getFullyConverted()) and - not hasNontrivialConversion(pointerToLocal) and - conservativeDataFlowStep+(DataFlow::exprNode(pointerToLocal), DataFlow::exprNode(r.getExpr())) + exists(Node mid | + branchlessLocalFlow1(mid) and + step(n, mid) ) ) -select r, "May return stack-allocated memory from $@.", va, va.toString() +} + +newtype TLocalPathNode = + TLocalPathNodeMid(Node n) { + branchlessLocalFlow1(n) and + ( + isSource(n) or + exists(LocalPathNodeMid mid | step(mid.getNode(), n)) + ) + } + +abstract class LocalPathNode extends TLocalPathNode { + Node n; + + /** Gets the underlying node. */ + Node getNode() { result = n } + + /** Gets a textual representation of this node. */ + string toString() { result = n.toString() } + + /** Gets the location of this element. */ + Location getLocation() { result = n.getLocation() } + + /** Gets a successor `LocalPathNode`, if any. */ + LocalPathNode getASuccessor() { step(this.getNode(), result.getNode()) } +} + +class LocalPathNodeMid extends LocalPathNode, TLocalPathNodeMid { + LocalPathNodeMid() { this = TLocalPathNodeMid(n) } +} + +class LocalPathNodeSink extends LocalPathNodeMid { + LocalPathNodeSink() { isSink(this.getNode()) } +} + +/** + * Holds if `source` is a source node, `sink` is a sink node, and there's flow + * from `source` to `sink` using `step` relation. + */ +predicate hasFlow(LocalPathNode source, LocalPathNodeSink sink) { + isSource(source.getNode()) and + source.getASuccessor+() = sink +} + +predicate reach(LocalPathNode n) { n instanceof LocalPathNodeSink or reach(n.getASuccessor()) } + +query predicate edges(LocalPathNode a, LocalPathNode b) { a.getASuccessor() = b and reach(b) } + +query predicate nodes(LocalPathNode n, string key, string val) { + reach(n) and key = "semmle.label" and val = n.toString() +} + +from LocalPathNode source, LocalPathNodeSink sink, VariableAddressInstruction var +where + hasFlow(source, sink) and + source.getNode().asInstruction() = var +select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAST(), + var.getAST().toString() diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected index 59a9ee1322c..8f9d91fc1ad 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected @@ -1,8 +1,231 @@ -| test.cpp:17:2:17:12 | return ... | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc | -| test.cpp:25:2:25:12 | return ... | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc | -| test.cpp:47:2:47:11 | return ... | May return stack-allocated memory from $@. | test.cpp:47:9:47:10 | mc | mc | -| test.cpp:54:2:54:16 | return ... | May return stack-allocated memory from $@. | test.cpp:54:11:54:12 | mc | mc | -| test.cpp:92:2:92:12 | return ... | May return stack-allocated memory from $@. | test.cpp:89:10:89:11 | mc | mc | -| test.cpp:112:2:112:12 | return ... | May return stack-allocated memory from $@. | test.cpp:112:9:112:11 | arr | arr | -| test.cpp:119:2:119:19 | return ... | May return stack-allocated memory from $@. | test.cpp:119:11:119:13 | arr | arr | -| test.cpp:171:3:171:24 | return ... | May return stack-allocated memory from $@. | test.cpp:170:35:170:41 | myLocal | myLocal | +edges +| test.cpp:17:9:17:11 | & ... | test.cpp:17:9:17:11 | StoreValue | +| test.cpp:17:10:17:11 | Unary | test.cpp:17:9:17:11 | & ... | +| test.cpp:17:10:17:11 | mc | test.cpp:17:10:17:11 | Unary | +| test.cpp:23:17:23:19 | & ... | test.cpp:23:17:23:19 | StoreValue | +| test.cpp:23:17:23:19 | Store | test.cpp:25:9:25:11 | Load | +| test.cpp:23:17:23:19 | StoreValue | test.cpp:23:17:23:19 | Store | +| test.cpp:23:18:23:19 | Unary | test.cpp:23:17:23:19 | & ... | +| test.cpp:23:18:23:19 | mc | test.cpp:23:18:23:19 | Unary | +| test.cpp:25:9:25:11 | Load | test.cpp:25:9:25:11 | ptr | +| test.cpp:25:9:25:11 | ptr | test.cpp:25:9:25:11 | StoreValue | +| test.cpp:39:17:39:18 | (reference to) | test.cpp:39:17:39:18 | StoreValue | +| test.cpp:39:17:39:18 | Store | test.cpp:41:10:41:12 | Load | +| test.cpp:39:17:39:18 | StoreValue | test.cpp:39:17:39:18 | Store | +| test.cpp:39:17:39:18 | Unary | test.cpp:39:17:39:18 | (reference to) | +| test.cpp:39:17:39:18 | mc | test.cpp:39:17:39:18 | Unary | +| test.cpp:41:9:41:12 | & ... | test.cpp:41:9:41:12 | StoreValue | +| test.cpp:41:10:41:12 | (reference dereference) | test.cpp:41:10:41:12 | Unary | +| test.cpp:41:10:41:12 | Load | test.cpp:41:10:41:12 | ref | +| test.cpp:41:10:41:12 | Unary | test.cpp:41:9:41:12 | & ... | +| test.cpp:41:10:41:12 | Unary | test.cpp:41:10:41:12 | (reference dereference) | +| test.cpp:41:10:41:12 | ref | test.cpp:41:10:41:12 | Unary | +| test.cpp:47:9:47:10 | (reference to) | test.cpp:47:9:47:10 | StoreValue | +| test.cpp:47:9:47:10 | Unary | test.cpp:47:9:47:10 | (reference to) | +| test.cpp:47:9:47:10 | mc | test.cpp:47:9:47:10 | Unary | +| test.cpp:54:9:54:15 | & ... | test.cpp:54:9:54:15 | StoreValue | +| test.cpp:54:11:54:12 | Unary | test.cpp:54:14:54:14 | a | +| test.cpp:54:11:54:12 | mc | test.cpp:54:11:54:12 | Unary | +| test.cpp:54:14:54:14 | Unary | test.cpp:54:9:54:15 | & ... | +| test.cpp:54:14:54:14 | a | test.cpp:54:14:54:14 | Unary | +| test.cpp:89:3:89:11 | Store | test.cpp:92:9:92:11 | Load | +| test.cpp:89:9:89:11 | & ... | test.cpp:89:9:89:11 | StoreValue | +| test.cpp:89:9:89:11 | StoreValue | test.cpp:89:3:89:11 | Store | +| test.cpp:89:10:89:11 | Unary | test.cpp:89:9:89:11 | & ... | +| test.cpp:89:10:89:11 | mc | test.cpp:89:10:89:11 | Unary | +| test.cpp:92:9:92:11 | Load | test.cpp:92:9:92:11 | ptr | +| test.cpp:92:9:92:11 | ptr | test.cpp:92:9:92:11 | StoreValue | +| test.cpp:112:9:112:11 | Unary | test.cpp:112:9:112:11 | array to pointer conversion | +| test.cpp:112:9:112:11 | arr | test.cpp:112:9:112:11 | Unary | +| test.cpp:112:9:112:11 | array to pointer conversion | test.cpp:112:9:112:11 | StoreValue | +| test.cpp:119:9:119:18 | & ... | test.cpp:119:9:119:18 | StoreValue | +| test.cpp:119:11:119:13 | Left | test.cpp:119:11:119:17 | access to array | +| test.cpp:119:11:119:13 | Unary | test.cpp:119:11:119:13 | array to pointer conversion | +| test.cpp:119:11:119:13 | arr | test.cpp:119:11:119:13 | Unary | +| test.cpp:119:11:119:13 | array to pointer conversion | test.cpp:119:11:119:13 | Left | +| test.cpp:119:11:119:17 | Unary | test.cpp:119:9:119:18 | & ... | +| test.cpp:119:11:119:17 | access to array | test.cpp:119:11:119:17 | Unary | +| test.cpp:134:2:134:14 | Store | test.cpp:135:2:135:4 | Load | +| test.cpp:134:8:134:10 | Left | test.cpp:134:8:134:14 | ... + ... | +| test.cpp:134:8:134:10 | Unary | test.cpp:134:8:134:10 | array to pointer conversion | +| test.cpp:134:8:134:10 | arr | test.cpp:134:8:134:10 | Unary | +| test.cpp:134:8:134:10 | array to pointer conversion | test.cpp:134:8:134:10 | Left | +| test.cpp:134:8:134:14 | ... + ... | test.cpp:134:8:134:14 | StoreValue | +| test.cpp:134:8:134:14 | StoreValue | test.cpp:134:2:134:14 | Store | +| test.cpp:135:2:135:4 | Left | test.cpp:135:2:135:6 | PointerAdd | +| test.cpp:135:2:135:4 | Load | test.cpp:135:2:135:4 | ptr | +| test.cpp:135:2:135:4 | ptr | test.cpp:135:2:135:4 | Left | +| test.cpp:135:2:135:6 | PointerAdd | test.cpp:135:2:135:6 | StoreValue | +| test.cpp:135:2:135:6 | Store | test.cpp:137:9:137:11 | Load | +| test.cpp:135:2:135:6 | StoreValue | test.cpp:135:2:135:6 | Store | +| test.cpp:137:9:137:11 | Load | test.cpp:137:9:137:11 | ptr | +| test.cpp:137:9:137:11 | ptr | test.cpp:137:9:137:11 | StoreValue | +| test.cpp:170:26:170:41 | (void *)... | test.cpp:170:26:170:41 | StoreValue | +| test.cpp:170:26:170:41 | Store | test.cpp:171:10:171:23 | Load | +| test.cpp:170:26:170:41 | StoreValue | test.cpp:170:26:170:41 | Store | +| test.cpp:170:34:170:41 | & ... | test.cpp:170:34:170:41 | Unary | +| test.cpp:170:34:170:41 | Unary | test.cpp:170:26:170:41 | (void *)... | +| test.cpp:170:35:170:41 | Unary | test.cpp:170:34:170:41 | & ... | +| test.cpp:170:35:170:41 | myLocal | test.cpp:170:35:170:41 | Unary | +| test.cpp:171:10:171:23 | Load | test.cpp:171:10:171:23 | pointerToLocal | +| test.cpp:171:10:171:23 | pointerToLocal | test.cpp:171:10:171:23 | StoreValue | +| test.cpp:176:25:176:34 | Store | test.cpp:177:10:177:23 | Load | +| test.cpp:176:25:176:34 | StoreValue | test.cpp:176:25:176:34 | Store | +| test.cpp:176:25:176:34 | Unary | test.cpp:176:25:176:34 | array to pointer conversion | +| test.cpp:176:25:176:34 | array to pointer conversion | test.cpp:176:25:176:34 | StoreValue | +| test.cpp:176:25:176:34 | localArray | test.cpp:176:25:176:34 | Unary | +| test.cpp:177:10:177:23 | (void *)... | test.cpp:177:10:177:23 | StoreValue | +| test.cpp:177:10:177:23 | Load | test.cpp:177:10:177:23 | pointerToLocal | +| test.cpp:177:10:177:23 | Unary | test.cpp:177:10:177:23 | (void *)... | +| test.cpp:177:10:177:23 | pointerToLocal | test.cpp:177:10:177:23 | Unary | +| test.cpp:182:21:182:27 | (reference to) | test.cpp:182:21:182:27 | StoreValue | +| test.cpp:182:21:182:27 | Store | test.cpp:183:10:183:19 | Load | +| test.cpp:182:21:182:27 | StoreValue | test.cpp:182:21:182:27 | Store | +| test.cpp:182:21:182:27 | Unary | test.cpp:182:21:182:27 | (reference to) | +| test.cpp:182:21:182:27 | myLocal | test.cpp:182:21:182:27 | Unary | +| test.cpp:183:10:183:19 | (reference dereference) | test.cpp:183:10:183:19 | Unary | +| test.cpp:183:10:183:19 | (reference to) | test.cpp:183:10:183:19 | StoreValue | +| test.cpp:183:10:183:19 | Load | test.cpp:183:10:183:19 | refToLocal | +| test.cpp:183:10:183:19 | Unary | test.cpp:183:10:183:19 | (reference dereference) | +| test.cpp:183:10:183:19 | Unary | test.cpp:183:10:183:19 | (reference to) | +| test.cpp:183:10:183:19 | refToLocal | test.cpp:183:10:183:19 | Unary | +| test.cpp:189:16:189:16 | (reference to) | test.cpp:189:16:189:16 | StoreValue | +| test.cpp:189:16:189:16 | Store | test.cpp:190:10:190:13 | Load | +| test.cpp:189:16:189:16 | StoreValue | test.cpp:189:16:189:16 | Store | +| test.cpp:189:16:189:16 | Unary | test.cpp:189:16:189:16 | (reference to) | +| test.cpp:189:16:189:16 | p | test.cpp:189:16:189:16 | Unary | +| test.cpp:190:10:190:13 | (reference dereference) | test.cpp:190:10:190:13 | Unary | +| test.cpp:190:10:190:13 | (reference to) | test.cpp:190:10:190:13 | StoreValue | +| test.cpp:190:10:190:13 | Load | test.cpp:190:10:190:13 | pRef | +| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference dereference) | +| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference to) | +| test.cpp:190:10:190:13 | pRef | test.cpp:190:10:190:13 | Unary | +nodes +| test.cpp:17:9:17:11 | & ... | semmle.label | & ... | +| test.cpp:17:9:17:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:17:10:17:11 | Unary | semmle.label | Unary | +| test.cpp:17:10:17:11 | mc | semmle.label | mc | +| test.cpp:23:17:23:19 | & ... | semmle.label | & ... | +| test.cpp:23:17:23:19 | Store | semmle.label | Store | +| test.cpp:23:17:23:19 | StoreValue | semmle.label | StoreValue | +| test.cpp:23:18:23:19 | Unary | semmle.label | Unary | +| test.cpp:23:18:23:19 | mc | semmle.label | mc | +| test.cpp:25:9:25:11 | Load | semmle.label | Load | +| test.cpp:25:9:25:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:25:9:25:11 | ptr | semmle.label | ptr | +| test.cpp:39:17:39:18 | (reference to) | semmle.label | (reference to) | +| test.cpp:39:17:39:18 | Store | semmle.label | Store | +| test.cpp:39:17:39:18 | StoreValue | semmle.label | StoreValue | +| test.cpp:39:17:39:18 | Unary | semmle.label | Unary | +| test.cpp:39:17:39:18 | mc | semmle.label | mc | +| test.cpp:41:9:41:12 | & ... | semmle.label | & ... | +| test.cpp:41:9:41:12 | StoreValue | semmle.label | StoreValue | +| test.cpp:41:10:41:12 | (reference dereference) | semmle.label | (reference dereference) | +| test.cpp:41:10:41:12 | Load | semmle.label | Load | +| test.cpp:41:10:41:12 | Unary | semmle.label | Unary | +| test.cpp:41:10:41:12 | Unary | semmle.label | Unary | +| test.cpp:41:10:41:12 | ref | semmle.label | ref | +| test.cpp:47:9:47:10 | (reference to) | semmle.label | (reference to) | +| test.cpp:47:9:47:10 | StoreValue | semmle.label | StoreValue | +| test.cpp:47:9:47:10 | Unary | semmle.label | Unary | +| test.cpp:47:9:47:10 | mc | semmle.label | mc | +| test.cpp:54:9:54:15 | & ... | semmle.label | & ... | +| test.cpp:54:9:54:15 | StoreValue | semmle.label | StoreValue | +| test.cpp:54:11:54:12 | Unary | semmle.label | Unary | +| test.cpp:54:11:54:12 | mc | semmle.label | mc | +| test.cpp:54:14:54:14 | Unary | semmle.label | Unary | +| test.cpp:54:14:54:14 | a | semmle.label | a | +| test.cpp:89:3:89:11 | Store | semmle.label | Store | +| test.cpp:89:9:89:11 | & ... | semmle.label | & ... | +| test.cpp:89:9:89:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:89:10:89:11 | Unary | semmle.label | Unary | +| test.cpp:89:10:89:11 | mc | semmle.label | mc | +| test.cpp:92:9:92:11 | Load | semmle.label | Load | +| test.cpp:92:9:92:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:92:9:92:11 | ptr | semmle.label | ptr | +| test.cpp:112:9:112:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:112:9:112:11 | Unary | semmle.label | Unary | +| test.cpp:112:9:112:11 | arr | semmle.label | arr | +| test.cpp:112:9:112:11 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:119:9:119:18 | & ... | semmle.label | & ... | +| test.cpp:119:9:119:18 | StoreValue | semmle.label | StoreValue | +| test.cpp:119:11:119:13 | Left | semmle.label | Left | +| test.cpp:119:11:119:13 | Unary | semmle.label | Unary | +| test.cpp:119:11:119:13 | arr | semmle.label | arr | +| test.cpp:119:11:119:13 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:119:11:119:17 | Unary | semmle.label | Unary | +| test.cpp:119:11:119:17 | access to array | semmle.label | access to array | +| test.cpp:134:2:134:14 | Store | semmle.label | Store | +| test.cpp:134:8:134:10 | Left | semmle.label | Left | +| test.cpp:134:8:134:10 | Unary | semmle.label | Unary | +| test.cpp:134:8:134:10 | arr | semmle.label | arr | +| test.cpp:134:8:134:10 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:134:8:134:14 | ... + ... | semmle.label | ... + ... | +| test.cpp:134:8:134:14 | StoreValue | semmle.label | StoreValue | +| test.cpp:135:2:135:4 | Left | semmle.label | Left | +| test.cpp:135:2:135:4 | Load | semmle.label | Load | +| test.cpp:135:2:135:4 | ptr | semmle.label | ptr | +| test.cpp:135:2:135:6 | PointerAdd | semmle.label | PointerAdd | +| test.cpp:135:2:135:6 | Store | semmle.label | Store | +| test.cpp:135:2:135:6 | StoreValue | semmle.label | StoreValue | +| test.cpp:137:9:137:11 | Load | semmle.label | Load | +| test.cpp:137:9:137:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:137:9:137:11 | ptr | semmle.label | ptr | +| test.cpp:170:26:170:41 | (void *)... | semmle.label | (void *)... | +| test.cpp:170:26:170:41 | Store | semmle.label | Store | +| test.cpp:170:26:170:41 | StoreValue | semmle.label | StoreValue | +| test.cpp:170:34:170:41 | & ... | semmle.label | & ... | +| test.cpp:170:34:170:41 | Unary | semmle.label | Unary | +| test.cpp:170:35:170:41 | Unary | semmle.label | Unary | +| test.cpp:170:35:170:41 | myLocal | semmle.label | myLocal | +| test.cpp:171:10:171:23 | Load | semmle.label | Load | +| test.cpp:171:10:171:23 | StoreValue | semmle.label | StoreValue | +| test.cpp:171:10:171:23 | pointerToLocal | semmle.label | pointerToLocal | +| test.cpp:176:25:176:34 | Store | semmle.label | Store | +| test.cpp:176:25:176:34 | StoreValue | semmle.label | StoreValue | +| test.cpp:176:25:176:34 | Unary | semmle.label | Unary | +| test.cpp:176:25:176:34 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:176:25:176:34 | localArray | semmle.label | localArray | +| test.cpp:177:10:177:23 | (void *)... | semmle.label | (void *)... | +| test.cpp:177:10:177:23 | Load | semmle.label | Load | +| test.cpp:177:10:177:23 | StoreValue | semmle.label | StoreValue | +| test.cpp:177:10:177:23 | Unary | semmle.label | Unary | +| test.cpp:177:10:177:23 | pointerToLocal | semmle.label | pointerToLocal | +| test.cpp:182:21:182:27 | (reference to) | semmle.label | (reference to) | +| test.cpp:182:21:182:27 | Store | semmle.label | Store | +| test.cpp:182:21:182:27 | StoreValue | semmle.label | StoreValue | +| test.cpp:182:21:182:27 | Unary | semmle.label | Unary | +| test.cpp:182:21:182:27 | myLocal | semmle.label | myLocal | +| test.cpp:183:10:183:19 | (reference dereference) | semmle.label | (reference dereference) | +| test.cpp:183:10:183:19 | (reference to) | semmle.label | (reference to) | +| test.cpp:183:10:183:19 | Load | semmle.label | Load | +| test.cpp:183:10:183:19 | StoreValue | semmle.label | StoreValue | +| test.cpp:183:10:183:19 | Unary | semmle.label | Unary | +| test.cpp:183:10:183:19 | Unary | semmle.label | Unary | +| test.cpp:183:10:183:19 | refToLocal | semmle.label | refToLocal | +| test.cpp:189:16:189:16 | (reference to) | semmle.label | (reference to) | +| test.cpp:189:16:189:16 | Store | semmle.label | Store | +| test.cpp:189:16:189:16 | StoreValue | semmle.label | StoreValue | +| test.cpp:189:16:189:16 | Unary | semmle.label | Unary | +| test.cpp:189:16:189:16 | p | semmle.label | p | +| test.cpp:190:10:190:13 | (reference dereference) | semmle.label | (reference dereference) | +| test.cpp:190:10:190:13 | (reference to) | semmle.label | (reference to) | +| test.cpp:190:10:190:13 | Load | semmle.label | Load | +| test.cpp:190:10:190:13 | StoreValue | semmle.label | StoreValue | +| test.cpp:190:10:190:13 | Unary | semmle.label | Unary | +| test.cpp:190:10:190:13 | Unary | semmle.label | Unary | +| test.cpp:190:10:190:13 | pRef | semmle.label | pRef | +#select +| test.cpp:17:9:17:11 | StoreValue | test.cpp:17:10:17:11 | mc | test.cpp:17:9:17:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc | +| test.cpp:25:9:25:11 | StoreValue | test.cpp:23:18:23:19 | mc | test.cpp:25:9:25:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc | +| test.cpp:41:9:41:12 | StoreValue | test.cpp:39:17:39:18 | mc | test.cpp:41:9:41:12 | StoreValue | May return stack-allocated memory from $@. | test.cpp:39:17:39:18 | mc | mc | +| test.cpp:47:9:47:10 | StoreValue | test.cpp:47:9:47:10 | mc | test.cpp:47:9:47:10 | StoreValue | May return stack-allocated memory from $@. | test.cpp:47:9:47:10 | mc | mc | +| test.cpp:54:9:54:15 | StoreValue | test.cpp:54:11:54:12 | mc | test.cpp:54:9:54:15 | StoreValue | May return stack-allocated memory from $@. | test.cpp:54:11:54:12 | mc | mc | +| test.cpp:92:9:92:11 | StoreValue | test.cpp:89:10:89:11 | mc | test.cpp:92:9:92:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:89:10:89:11 | mc | mc | +| test.cpp:112:9:112:11 | StoreValue | test.cpp:112:9:112:11 | arr | test.cpp:112:9:112:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:112:9:112:11 | arr | arr | +| test.cpp:119:9:119:18 | StoreValue | test.cpp:119:11:119:13 | arr | test.cpp:119:9:119:18 | StoreValue | May return stack-allocated memory from $@. | test.cpp:119:11:119:13 | arr | arr | +| test.cpp:137:9:137:11 | StoreValue | test.cpp:134:8:134:10 | arr | test.cpp:137:9:137:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:134:8:134:10 | arr | arr | +| test.cpp:171:10:171:23 | StoreValue | test.cpp:170:35:170:41 | myLocal | test.cpp:171:10:171:23 | StoreValue | May return stack-allocated memory from $@. | test.cpp:170:35:170:41 | myLocal | myLocal | +| test.cpp:177:10:177:23 | StoreValue | test.cpp:176:25:176:34 | localArray | test.cpp:177:10:177:23 | StoreValue | May return stack-allocated memory from $@. | test.cpp:176:25:176:34 | localArray | localArray | +| test.cpp:183:10:183:19 | StoreValue | test.cpp:182:21:182:27 | myLocal | test.cpp:183:10:183:19 | StoreValue | May return stack-allocated memory from $@. | test.cpp:182:21:182:27 | myLocal | myLocal | +| test.cpp:190:10:190:13 | StoreValue | test.cpp:189:16:189:16 | p | test.cpp:190:10:190:13 | StoreValue | May return stack-allocated memory from $@. | test.cpp:189:16:189:16 | p | p | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp index 1ce2558a34f..abbca07cc4b 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp @@ -38,7 +38,7 @@ MyClass *test4() MyClass mc; MyClass &ref = mc; - return &ref; // BAD [NOT DETECTED] + return &ref; // BAD } MyClass &test5() @@ -134,7 +134,7 @@ char *testArray4() ptr = arr + 1; ptr++; - return ptr; // BAD [NOT DETECTED] + return ptr; // BAD } char *testArray5() @@ -174,20 +174,20 @@ void *conversionBeforeDataFlow() { void *arrayConversionBeforeDataFlow() { int localArray[4]; int *pointerToLocal = localArray; // has conversion - return pointerToLocal; // BAD [NOT DETECTED] + return pointerToLocal; // BAD } int &dataFlowThroughReference() { int myLocal; int &refToLocal = myLocal; // has conversion - return refToLocal; // BAD [NOT DETECTED] + return refToLocal; // BAD } int *&conversionInFlow() { int myLocal; int *p = &myLocal; int *&pRef = p; // has conversion in the middle of data flow - return pRef; // BAD [NOT DETECTED] + return pRef; // BAD } namespace std { @@ -215,4 +215,4 @@ auto make_read_port() auto port = std::shared_ptr(new int); auto ptr = port.get(); return ptr; // GOOD -} \ No newline at end of file +} From bd1720f79744d69c81b6a2a9001024567b15b53b Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 20 Jan 2022 18:27:09 +0000 Subject: [PATCH 173/196] C++: Add change note. --- .../change-notes/2022-01-20-return-stack-allocated-memory.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 cpp/ql/src/change-notes/2022-01-20-return-stack-allocated-memory.md diff --git a/cpp/ql/src/change-notes/2022-01-20-return-stack-allocated-memory.md b/cpp/ql/src/change-notes/2022-01-20-return-stack-allocated-memory.md new file mode 100644 index 00000000000..ff51d88a94e --- /dev/null +++ b/cpp/ql/src/change-notes/2022-01-20-return-stack-allocated-memory.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* The `cpp/return-stack-allocated-memory` query has been improved to produce fewer false positives. The + query has also been converted to a `path-problem` query. \ No newline at end of file From f1a2b21e440b37c128c263cd315c06069063d866 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 21 Jan 2022 09:29:40 +0100 Subject: [PATCH 174/196] Data flow: Restructure `RequiredSummaryComponentStack` --- .../dataflow/internal/FlowSummaryImpl.qll | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 60af91e291b..4576e349df4 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -171,15 +171,20 @@ module Public { ) } + private newtype TRequiredSummaryComponentStack = MkRequiredSummaryComponentStack() + /** * A class that exists for QL technical reasons only (the IPA type used * to represent component stacks needs to be bounded). */ - abstract class RequiredSummaryComponentStack extends SummaryComponentStack { + class RequiredSummaryComponentStack extends TRequiredSummaryComponentStack { + /** Gets a textual representation of this element. */ + string toString() { none() } + /** * Holds if the stack obtained by pushing `head` onto `tail` is required. */ - abstract predicate required(SummaryComponent c); + predicate required(SummaryComponent head, SummaryComponentStack tail) { none() } } /** A callable with a flow summary. */ @@ -240,9 +245,9 @@ module Private { newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or TConsSummaryComponentStack(SummaryComponent head, SummaryComponentStack tail) { - tail.(RequiredSummaryComponentStack).required(head) + any(RequiredSummaryComponentStack x).required(head, tail) or - tail.(RequiredSummaryComponentStack).required(TParameterSummaryComponent(_)) and + any(RequiredSummaryComponentStack x).required(TParameterSummaryComponent(_), tail) and head = thisParam() or derivedFluentFlowPush(_, _, _, head, tail, _) @@ -890,9 +895,9 @@ module Private { } private class MkStack extends RequiredSummaryComponentStack { - MkStack() { interpretSpec(_, _, _, this) } - - override predicate required(SummaryComponent c) { interpretSpec(_, _, c, this) } + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + interpretSpec(_, _, head, tail) + } } private class SummarizedCallableExternal extends SummarizedCallable { From cba733136c9a101d66f2b6fc818aa23a699857aa Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 21 Jan 2022 09:30:01 +0100 Subject: [PATCH 175/196] Data flow: Sync --- .../dataflow/internal/FlowSummaryImpl.qll | 19 ++++++++++++------- .../dataflow/internal/FlowSummaryImpl.qll | 19 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 60af91e291b..4576e349df4 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -171,15 +171,20 @@ module Public { ) } + private newtype TRequiredSummaryComponentStack = MkRequiredSummaryComponentStack() + /** * A class that exists for QL technical reasons only (the IPA type used * to represent component stacks needs to be bounded). */ - abstract class RequiredSummaryComponentStack extends SummaryComponentStack { + class RequiredSummaryComponentStack extends TRequiredSummaryComponentStack { + /** Gets a textual representation of this element. */ + string toString() { none() } + /** * Holds if the stack obtained by pushing `head` onto `tail` is required. */ - abstract predicate required(SummaryComponent c); + predicate required(SummaryComponent head, SummaryComponentStack tail) { none() } } /** A callable with a flow summary. */ @@ -240,9 +245,9 @@ module Private { newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or TConsSummaryComponentStack(SummaryComponent head, SummaryComponentStack tail) { - tail.(RequiredSummaryComponentStack).required(head) + any(RequiredSummaryComponentStack x).required(head, tail) or - tail.(RequiredSummaryComponentStack).required(TParameterSummaryComponent(_)) and + any(RequiredSummaryComponentStack x).required(TParameterSummaryComponent(_), tail) and head = thisParam() or derivedFluentFlowPush(_, _, _, head, tail, _) @@ -890,9 +895,9 @@ module Private { } private class MkStack extends RequiredSummaryComponentStack { - MkStack() { interpretSpec(_, _, _, this) } - - override predicate required(SummaryComponent c) { interpretSpec(_, _, c, this) } + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + interpretSpec(_, _, head, tail) + } } private class SummarizedCallableExternal extends SummarizedCallable { diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll index 60af91e291b..4576e349df4 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll @@ -171,15 +171,20 @@ module Public { ) } + private newtype TRequiredSummaryComponentStack = MkRequiredSummaryComponentStack() + /** * A class that exists for QL technical reasons only (the IPA type used * to represent component stacks needs to be bounded). */ - abstract class RequiredSummaryComponentStack extends SummaryComponentStack { + class RequiredSummaryComponentStack extends TRequiredSummaryComponentStack { + /** Gets a textual representation of this element. */ + string toString() { none() } + /** * Holds if the stack obtained by pushing `head` onto `tail` is required. */ - abstract predicate required(SummaryComponent c); + predicate required(SummaryComponent head, SummaryComponentStack tail) { none() } } /** A callable with a flow summary. */ @@ -240,9 +245,9 @@ module Private { newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or TConsSummaryComponentStack(SummaryComponent head, SummaryComponentStack tail) { - tail.(RequiredSummaryComponentStack).required(head) + any(RequiredSummaryComponentStack x).required(head, tail) or - tail.(RequiredSummaryComponentStack).required(TParameterSummaryComponent(_)) and + any(RequiredSummaryComponentStack x).required(TParameterSummaryComponent(_), tail) and head = thisParam() or derivedFluentFlowPush(_, _, _, head, tail, _) @@ -890,9 +895,9 @@ module Private { } private class MkStack extends RequiredSummaryComponentStack { - MkStack() { interpretSpec(_, _, _, this) } - - override predicate required(SummaryComponent c) { interpretSpec(_, _, c, this) } + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + interpretSpec(_, _, head, tail) + } } private class SummarizedCallableExternal extends SummarizedCallable { From f9b906d1e27f1dd77c13a31650e0864e50530535 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 21 Jan 2022 09:30:09 +0100 Subject: [PATCH 176/196] C#: Update uses of `RequiredSummaryComponentStack` --- .../code/csharp/dataflow/FlowSummary.qll | 8 ++----- .../csharp/frameworks/EntityFramework.qll | 24 +++++++------------ 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll index 270991757f6..3ae9c7667d0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll @@ -153,15 +153,11 @@ private class SummarizedCallableDefaultClearsContent extends Impl::Public::Summa class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack; private class RecordConstructorFlowRequiredSummaryComponentStack extends RequiredSummaryComponentStack { - private SummaryComponent head; - - RecordConstructorFlowRequiredSummaryComponentStack() { + override predicate required(SummaryComponent head, SummaryComponentStack tail) { exists(Property p | recordConstructorFlow(_, _, p) and head = SummaryComponent::property(p) and - this = SummaryComponentStack::return() + tail = SummaryComponentStack::return() ) } - - override predicate required(SummaryComponent c) { c = head } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll index b586c4cffb1..5def0963292 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll @@ -91,14 +91,10 @@ module EntityFramework { abstract class EFSummarizedCallable extends SummarizedCallable { } private class DbSetAddOrUpdateRequiredSummaryComponentStack extends RequiredSummaryComponentStack { - private SummaryComponent head; - - DbSetAddOrUpdateRequiredSummaryComponentStack() { - this = SummaryComponentStack::argument([-1, 0]) and - head = SummaryComponent::element() + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + head = SummaryComponent::element() and + tail = SummaryComponentStack::argument([-1, 0]) } - - override predicate required(SummaryComponent c) { c = head } } private class DbSetAddOrUpdate extends EFSummarizedCallable { @@ -462,14 +458,12 @@ module EntityFramework { } private class DbContextSaveChangesRequiredSummaryComponentStack extends RequiredSummaryComponentStack { - private Content head; - - DbContextSaveChangesRequiredSummaryComponentStack() { - any(DbContextClass c).requiresComponentStackIn(head, _, this, _) - or - any(DbContextClass c).requiresComponentStackOut(head, _, this, _) + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + exists(Content c | head = SummaryComponent::content(c) | + any(DbContextClass cls).requiresComponentStackIn(c, _, tail, _) + or + any(DbContextClass cls).requiresComponentStackOut(c, _, tail, _) + ) } - - override predicate required(SummaryComponent c) { c = SummaryComponent::content(head) } } } From d22632ef789df8519cafe35e11f0cc5812383131 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jan 2022 10:48:00 +0100 Subject: [PATCH 177/196] Fix recursion in entrypointFieldStep When using local taint tracking to define a RemoteFlowSource, a recursion was created because entrypointFieldStep adds new RemoteFlowSources and was a local taint step. This is fixed by converting entrypointFieldStep into a defaultAdditionalTaintStep instead of a localAdditionalTaintStep, i.e. it will only affect global taint tracking from now on. --- .../semmle/code/java/dataflow/internal/TaintTrackingUtil.qll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index b1840e56212..59608d792f2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -92,8 +92,6 @@ private module Cached { ) or FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false) - or - entrypointFieldStep(src, sink) } /** @@ -103,6 +101,7 @@ private module Cached { cached predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { localAdditionalTaintStep(src, sink) or + entrypointFieldStep(src, sink) or any(AdditionalTaintStep a).step(src, sink) } From 3f6e035016ccc282b0d4c6a7ef0d74690529f2cf Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Fri, 21 Jan 2022 11:37:02 +0100 Subject: [PATCH 178/196] Docs improvements --- .../CWE/CWE-927/ImplicitPendingIntents.qhelp | 44 +++++++++---------- .../CWE/CWE-927/ImplicitPendingIntents.ql | 6 +-- ...1-12-21-android-implicit-pendingintents.md | 6 +-- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp index 5fd407b93ae..1931e8e4fef 100644 --- a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp +++ b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp @@ -5,42 +5,42 @@ -

    A PendingIntent describes an action in the form of an Intent that is intended to be given and executed - at a later time by another application. The Intent wrapped by a PendingIntent is executed on behalf of - the application that created it, and with its same privileges.

    -

    If a PendingIntent is configured to be mutable, the fields of its internal Intent can be changed by the - receiving application if they were not previously set. This means that a mutable PendingIntent that has - not defined a destination component (that is, an implicit PendingIntent) can be altered to execute an +

    A PendingIntent is used to wrap an Intent that will be supplied and executed by another + application. When the Intent is executed, it behaves as if it were run directly by the supplying + application, using the privileges of that application.

    +

    If a PendingIntent is configured to be mutable, the fields of its internal Intent can be changed by the + receiving application if they were not previously set. This means that a mutable PendingIntent that has + not defined a destination component (that is, an implicit PendingIntent) can be altered to execute an arbitrary action with the privileges of the application that created it.

    -

    If an implicit PendingIntent is obtainable by a malicious application by any of the following means:

    +

    A malicious application can access an implicit PendingIntent as follows:

      -
    • It is wrapped and sent as an extra of another implicit Intent
    • -
    • It is sent as the action of a Slide
    • -
    • It is sent as the action of a Notification
    • +
    • It is wrapped and sent as an extra of another implicit Intent.
    • +
    • It is sent as the action of a Slide.
    • +
    • It is sent as the action of a Notification.

    -

    the attacker could modify the underlying Intent and execute an arbitrary action with elevated privileges. - This could give the malicious application access to private components of the victim application, - or the ability to perform actions without having the necessary permissions.

    +

    On gaining access, the attacker can modify the underlying Intent and execute an arbitrary action + with elevated privileges. This could give the malicious application access to private components of the victim + application, or the ability to perform actions without having the necessary permissions.

    -

    Avoid creating implicit PendingIntents. This means that the underlying Intent should always have an +

    Avoid creating implicit PendingIntents. This means that the underlying Intent should always have an explicit destination component.

    -

    Also, when adding the PendingIntent as an extra of another Intent, make sure that said Intent also has +

    Also, when adding the PendingIntent as an extra of another Intent, make sure that said Intent also has an explicit destination component, so that it is not delivered to untrusted applications.

    -

    It is also recommended to create the PendingIntent using the flag FLAG_IMMUTABLE whenever - possible, to prevent the destination component from modifying empty fields of the underlying Intent.

    +

    Create the PendingIntent using the flag FLAG_IMMUTABLE whenever possible, + to prevent the destination component from modifying empty fields of the underlying Intent.

    -

    In the following examples, a PendingIntent is created and wrapped as an extra of another Intent. +

    In the following examples, a PendingIntent is created and wrapped as an extra of another Intent.

    -

    In the first example, both the PendingIntent and the Intent it is wrapped in are implicit, - reproducing the vulnerability.

    +

    In the first example, both the PendingIntent and the Intent it is wrapped in are implicit, + making them vulnerable to attack.

    In the second example, the issue is avoided by adding explicit destination components to the - PendingIntent and the wrapping Intent.

    -

    The third example uses the FLAG_IMMUTABLE flag to prevent the underlying Intent from being modified + PendingIntent and the wrapping Intent.

    +

    The third example uses the FLAG_IMMUTABLE flag to prevent the underlying Intent from being modified by the destination component.

    diff --git a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql index e6aff45524d..4d8056f68cd 100644 --- a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql +++ b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql @@ -1,8 +1,8 @@ /** * @name Use of implicit PendingIntents - * @description Implicit and mutable PendingIntents being sent to an unspecified third party - * component may provide access to internal components of the application or cause - * other unintended effects. + * @description Sending an implicit and mutable 'PendingIntent' to an unspecified third party + * component may provide an attacker with access to internal components of the + * application or cause other unintended effects. * @kind path-problem * @problem.severity error * @security-severity 8.2 diff --git a/java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md b/java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md index a752d5c5ccd..8549f3863a6 100644 --- a/java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md +++ b/java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md @@ -2,6 +2,6 @@ category: newQuery --- * A new query "Use of implicit PendingIntents" (`java/android/pending-intents`) has been added. -This query finds implicit and mutable `PendingIntents` being sent to an unspecified third party component, -which can provide access to internal components of the application or cause other unintended -effects. \ No newline at end of file +This query finds implicit and mutable `PendingIntents` sent to an unspecified third party +component, which may provide an attacker with access to internal components of the application +or cause other unintended effects. \ No newline at end of file From ddfc3bc00f461cea9f9a18236af388f3a8c6a287 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 20 Jan 2022 22:43:00 +0100 Subject: [PATCH 179/196] use set literals instead of big disjunctions --- .../code/java/frameworks/struts/StrutsConventions.qll | 7 +------ .../src/Likely Bugs/Comparison/UselessComparisonTest.qll | 7 +------ python/ql/lib/semmle/python/web/cherrypy/Request.qll | 7 +------ python/ql/lib/semmle/python/web/flask/Request.qll | 5 +---- python/ql/lib/semmle/python/web/tornado/Request.qll | 5 +---- python/ql/lib/semmle/python/web/twisted/Request.qll | 7 +------ .../ql/src/Expressions/Formatting/AdvancedFormatting.qll | 4 +--- python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql | 2 +- python/ql/src/Statements/ModificationOfLocals.ql | 5 +---- python/ql/test/library-tests/PointsTo/api/Constants.ql | 2 +- 10 files changed, 10 insertions(+), 41 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll index 35faa0e55ff..0f38147ad13 100644 --- a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll +++ b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll @@ -101,12 +101,7 @@ class Struts2ConventionActionClass extends Class { exists(string ancestorPackage | // Has an ancestor package on the whitelist ancestorPackage = this.getPackage().getName().splitAt(".") and - ( - ancestorPackage = "struts" or - ancestorPackage = "struts2" or - ancestorPackage = "action" or - ancestorPackage = "actions" - ) + ancestorPackage = ["struts", "struts2", "action", "actions"] ) and ( this.getName().matches("%" + getConventionSuffix(this)) or diff --git a/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll b/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll index ea01b89deb3..d17f62cd76f 100644 --- a/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll +++ b/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll @@ -7,12 +7,7 @@ import semmle.code.java.dataflow.SSA * The kind of bound that is known to hold for some variable. */ library class BoundKind extends string { - BoundKind() { - this = "=" or - this = "!=" or - this = ">=" or - this = "<=" - } + BoundKind() { this = ["=", "!=", ">=", "<="] } predicate isEqual() { this = "=" } diff --git a/python/ql/lib/semmle/python/web/cherrypy/Request.qll b/python/ql/lib/semmle/python/web/cherrypy/Request.qll index 094474b8915..81ea03e93fd 100644 --- a/python/ql/lib/semmle/python/web/cherrypy/Request.qll +++ b/python/ql/lib/semmle/python/web/cherrypy/Request.qll @@ -15,12 +15,7 @@ class CherryPyRequest extends TaintKind { } override TaintKind getTaintOfMethodResult(string name) { - ( - name = "getHeader" or - name = "getCookie" or - name = "getUser" or - name = "getPassword" - ) and + name in ["getHeader", "getCookie", "getUser", "getPassword"] and result instanceof ExternalStringKind } } diff --git a/python/ql/lib/semmle/python/web/flask/Request.qll b/python/ql/lib/semmle/python/web/flask/Request.qll index 67bf77a5ac5..2f6b7758b8a 100644 --- a/python/ql/lib/semmle/python/web/flask/Request.qll +++ b/python/ql/lib/semmle/python/web/flask/Request.qll @@ -16,10 +16,7 @@ class FlaskRequestData extends HttpRequestTaintSource { FlaskRequestData() { not this instanceof FlaskRequestArgs and exists(string name | flask_request_attr(this, name) | - name = "path" or - name = "full_path" or - name = "base_url" or - name = "url" + name in ["path", "full_path", "base_url", "url"] ) } diff --git a/python/ql/lib/semmle/python/web/tornado/Request.qll b/python/ql/lib/semmle/python/web/tornado/Request.qll index 1dde3379117..48b608b1223 100644 --- a/python/ql/lib/semmle/python/web/tornado/Request.qll +++ b/python/ql/lib/semmle/python/web/tornado/Request.qll @@ -41,10 +41,7 @@ class TornadoRequestSource extends HttpRequestTaintSource { class TornadoExternalInputSource extends HttpRequestTaintSource { TornadoExternalInputSource() { exists(string name | - name = "get_argument" or - name = "get_query_argument" or - name = "get_body_argument" or - name = "decode_argument" + name in ["get_argument", "get_query_argument", "get_body_argument", "decode_argument"] | this = callToNamedTornadoRequestHandlerMethod(name) ) diff --git a/python/ql/lib/semmle/python/web/twisted/Request.qll b/python/ql/lib/semmle/python/web/twisted/Request.qll index e164de585d1..85973bb20d5 100644 --- a/python/ql/lib/semmle/python/web/twisted/Request.qll +++ b/python/ql/lib/semmle/python/web/twisted/Request.qll @@ -16,12 +16,7 @@ class TwistedRequest extends TaintKind { } override TaintKind getTaintOfMethodResult(string name) { - ( - name = "getHeader" or - name = "getCookie" or - name = "getUser" or - name = "getPassword" - ) and + name in ["getHeader", "getCookie", "getUser", "getPassword"] and result instanceof ExternalStringKind } } diff --git a/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll b/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll index 4941a5f4f1f..7849c881338 100644 --- a/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll +++ b/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll @@ -40,9 +40,7 @@ library class PossibleAdvancedFormatString extends StrConst { private predicate implicitlyNumberedField(int start, int end) { this.field(start, end) and - exists(string c | start + 1 = this.getText().indexOf(c) | - c = "}" or c = ":" or c = "!" or c = "." - ) + exists(string c | start + 1 = this.getText().indexOf(c) | c in ["}", ":", "!", "."]) } /** Whether this format string has implicitly numbered fields */ diff --git a/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql b/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql index 895c8714ddf..dc760df424f 100644 --- a/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql +++ b/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql @@ -32,7 +32,7 @@ predicate duplicate_char_in_class(Regex r, string char) { //Ignore whitespace in verbose mode not ( r.getAMode() = "VERBOSE" and - (char = " " or char = "\t" or char = "\r" or char = "\n") + char in [" ", "\t", "\r", "\n"] ) } diff --git a/python/ql/src/Statements/ModificationOfLocals.ql b/python/ql/src/Statements/ModificationOfLocals.ql index 5a87d60edf2..f766000ec3e 100644 --- a/python/ql/src/Statements/ModificationOfLocals.ql +++ b/python/ql/src/Statements/ModificationOfLocals.ql @@ -22,10 +22,7 @@ predicate modification_of_locals(ControlFlowNode f) { attr = f.(CallNode).getFunction() and originIsLocals(attr.getObject(mname)) | - mname = "pop" or - mname = "popitem" or - mname = "update" or - mname = "clear" + mname in ["pop", "popitem", "update", "clear"] ) } diff --git a/python/ql/test/library-tests/PointsTo/api/Constants.ql b/python/ql/test/library-tests/PointsTo/api/Constants.ql index e44e52b4b9f..151f6b9ce9c 100644 --- a/python/ql/test/library-tests/PointsTo/api/Constants.ql +++ b/python/ql/test/library-tests/PointsTo/api/Constants.ql @@ -7,7 +7,7 @@ where or txt = "b'" + s + "'" and val = Value::forBytes(s) | - s = "a" or s = "b" or s = "c" or s = "d" + s in ["a", "b", "c", "d"] ) or exists(int i | txt = i.toString() and val = Value::forInt(i) | From f500bccbe47fa37c1458c37cdfc522d2eabd78d4 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 20 Jan 2022 22:28:44 +0100 Subject: [PATCH 180/196] add explicit this to member call --- cpp/ql/lib/semmle/code/cpp/commons/Printf.qll | 4 +- .../semmle/code/cpp/security/BufferWrite.qll | 50 +++-- csharp/ql/test/shared/FlowSummaries.qll | 2 +- .../semmle/code/java/frameworks/Servlets.qll | 172 +++++++++--------- .../semmle/code/java/security/Encryption.qll | 4 +- .../src/semmle/code/xml/MyBatisMapperXML.qll | 2 +- .../ql/lib/semmle/javascript/ApiGraphs.qll | 2 +- .../ql/lib/semmle/javascript/Routing.qll | 96 +++++----- .../dependencies/FrameworkLibraries.qll | 10 +- .../semmle/javascript/frameworks/Express.qll | 12 +- .../semmle/javascript/frameworks/Fastify.qll | 41 +++-- .../lib/semmle/javascript/frameworks/HTTP.qll | 2 +- .../javascript/frameworks/Templating.qll | 4 +- .../security/dataflow/MissingRateLimiting.qll | 2 +- ruby/ql/lib/codeql/ruby/ast/Pattern.qll | 8 +- .../internal/ControlFlowGraphImpl.qll | 4 +- ruby/ql/test/TestUtilities/InlineFlowTest.qll | 5 +- 17 files changed, 222 insertions(+), 198 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll index 5ee7245d6e7..4a6566da45d 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll @@ -1122,7 +1122,7 @@ class FormatLiteral extends Literal { * conversion specifier of this format string; has no result if this cannot * be determined. */ - int getMaxConvertedLength(int n) { result = max(getMaxConvertedLength(n, _)) } + int getMaxConvertedLength(int n) { result = max(this.getMaxConvertedLength(n, _)) } /** * Gets the maximum length of the string that can be produced by the nth @@ -1353,7 +1353,7 @@ class FormatLiteral extends Literal { * determining whether a buffer overflow is caused by long float to string * conversions. */ - int getMaxConvertedLengthLimited(int n) { result = max(getMaxConvertedLengthLimited(n, _)) } + int getMaxConvertedLengthLimited(int n) { result = max(this.getMaxConvertedLengthLimited(n, _)) } /** * Gets the maximum length of the string that can be produced by the nth diff --git a/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll b/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll index ca9dd56436e..a980de9785d 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll @@ -76,7 +76,7 @@ abstract class BufferWrite extends Expr { * can be found), specifying the reason for the estimation. */ int getMaxData(BufferWriteEstimationReason reason) { - reason instanceof UnspecifiedEstimateReason and result = getMaxData() + reason instanceof UnspecifiedEstimateReason and result = this.getMaxData() } /** @@ -85,7 +85,7 @@ abstract class BufferWrite extends Expr { * much smaller (8 bytes) than their true maximum length. This can be * helpful in determining the cause of a buffer overflow issue. */ - int getMaxDataLimited() { result = getMaxData() } + int getMaxDataLimited() { result = this.getMaxData() } /** * Gets an upper bound to the amount of data that's being written (if one @@ -94,7 +94,7 @@ abstract class BufferWrite extends Expr { * than their true maximum length. This can be helpful in determining the * cause of a buffer overflow issue. */ - int getMaxDataLimited(BufferWriteEstimationReason reason) { result = getMaxData(reason) } + int getMaxDataLimited(BufferWriteEstimationReason reason) { result = this.getMaxData(reason) } /** * Gets the size of a single character of the type this @@ -159,9 +159,11 @@ class StrCopyBW extends BufferWriteCall { this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize() } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } } /** @@ -203,9 +205,11 @@ class StrCatBW extends BufferWriteCall { this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize() } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } } /** @@ -269,9 +273,11 @@ class SprintfBW extends BufferWriteCall { ) } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } private int getMaxDataLimitedImpl(BufferWriteEstimationReason reason) { exists(FormatLiteral fl | @@ -281,10 +287,10 @@ class SprintfBW extends BufferWriteCall { } override int getMaxDataLimited(BufferWriteEstimationReason reason) { - result = getMaxDataLimitedImpl(reason) + result = this.getMaxDataLimitedImpl(reason) } - override int getMaxDataLimited() { result = max(getMaxDataLimitedImpl(_)) } + override int getMaxDataLimited() { result = max(this.getMaxDataLimitedImpl(_)) } } /** @@ -382,9 +388,11 @@ class SnprintfBW extends BufferWriteCall { ) } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } private int getMaxDataLimitedImpl(BufferWriteEstimationReason reason) { exists(FormatLiteral fl | @@ -394,10 +402,10 @@ class SnprintfBW extends BufferWriteCall { } override int getMaxDataLimited(BufferWriteEstimationReason reason) { - result = getMaxDataLimitedImpl(reason) + result = this.getMaxDataLimitedImpl(reason) } - override int getMaxDataLimited() { result = max(getMaxDataLimitedImpl(_)) } + override int getMaxDataLimited() { result = max(this.getMaxDataLimitedImpl(_)) } } /** @@ -495,9 +503,11 @@ class ScanfBW extends BufferWrite { ) } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } override string getBWDesc() { exists(FunctionCall fc | @@ -536,7 +546,9 @@ class RealpathBW extends BufferWriteCall { this = this // Suppress a compiler warning } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } } diff --git a/csharp/ql/test/shared/FlowSummaries.qll b/csharp/ql/test/shared/FlowSummaries.qll index d8350f71b7f..6afa16a744a 100644 --- a/csharp/ql/test/shared/FlowSummaries.qll +++ b/csharp/ql/test/shared/FlowSummaries.qll @@ -38,7 +38,7 @@ abstract class IncludeSummarizedCallable extends RelevantSummarizedCallable { this.getDeclaringType().hasQualifiedName(namespace, type) and result = namespace + ";" + type + ";" + this.getCallableOverride() + ";" + this.getName() + ";" + "(" - + parameterQualifiedTypeNamesToString() + ")" + + this.parameterQualifiedTypeNamesToString() + ")" ) } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll index d9988e31f67..81f334015bd 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll @@ -10,7 +10,7 @@ import semmle.code.java.Type */ library class ServletRequest extends RefType { ServletRequest() { - hasQualifiedName("javax.servlet", "ServletRequest") or + this.hasQualifiedName("javax.servlet", "ServletRequest") or this instanceof HttpServletRequest } } @@ -19,7 +19,7 @@ library class ServletRequest extends RefType { * The interface `javax.servlet.http.HttpServletRequest`. */ library class HttpServletRequest extends RefType { - HttpServletRequest() { hasQualifiedName("javax.servlet.http", "HttpServletRequest") } + HttpServletRequest() { this.hasQualifiedName("javax.servlet.http", "HttpServletRequest") } } /** @@ -28,13 +28,13 @@ library class HttpServletRequest extends RefType { */ library class ServletRequestGetParameterMethod extends Method { ServletRequestGetParameterMethod() { - getDeclaringType() instanceof ServletRequest and + this.getDeclaringType() instanceof ServletRequest and ( - hasName("getParameter") or - hasName("getParameterValues") + this.hasName("getParameter") or + this.hasName("getParameterValues") ) and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof TypeString } } @@ -43,9 +43,9 @@ library class ServletRequestGetParameterMethod extends Method { */ library class ServletRequestGetParameterNamesMethod extends Method { ServletRequestGetParameterNamesMethod() { - getDeclaringType() instanceof ServletRequest and - hasName("getParameterNames") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof ServletRequest and + this.hasName("getParameterNames") and + this.getNumberOfParameters() = 0 } } @@ -54,9 +54,9 @@ library class ServletRequestGetParameterNamesMethod extends Method { */ library class ServletRequestGetParameterMapMethod extends Method { ServletRequestGetParameterMapMethod() { - getDeclaringType() instanceof ServletRequest and - hasName("getParameterMap") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof ServletRequest and + this.hasName("getParameterMap") and + this.getNumberOfParameters() = 0 } } @@ -65,9 +65,9 @@ library class ServletRequestGetParameterMapMethod extends Method { */ library class HttpServletRequestGetQueryStringMethod extends Method { HttpServletRequestGetQueryStringMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getQueryString") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getQueryString") and + this.getNumberOfParameters() = 0 } } @@ -76,9 +76,9 @@ library class HttpServletRequestGetQueryStringMethod extends Method { */ class HttpServletRequestGetPathMethod extends Method { HttpServletRequestGetPathMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getPathInfo") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getPathInfo") and + this.getNumberOfParameters() = 0 } } @@ -87,10 +87,10 @@ class HttpServletRequestGetPathMethod extends Method { */ library class HttpServletRequestGetHeaderMethod extends Method { HttpServletRequestGetHeaderMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getHeader") and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getHeader") and + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof TypeString } } @@ -99,10 +99,10 @@ library class HttpServletRequestGetHeaderMethod extends Method { */ library class HttpServletRequestGetHeadersMethod extends Method { HttpServletRequestGetHeadersMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getHeaders") and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getHeaders") and + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof TypeString } } @@ -111,9 +111,9 @@ library class HttpServletRequestGetHeadersMethod extends Method { */ library class HttpServletRequestGetHeaderNamesMethod extends Method { HttpServletRequestGetHeaderNamesMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getHeaderNames") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getHeaderNames") and + this.getNumberOfParameters() = 0 } } @@ -122,9 +122,9 @@ library class HttpServletRequestGetHeaderNamesMethod extends Method { */ class HttpServletRequestGetRequestURLMethod extends Method { HttpServletRequestGetRequestURLMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getRequestURL") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getRequestURL") and + this.getNumberOfParameters() = 0 } } @@ -133,9 +133,9 @@ class HttpServletRequestGetRequestURLMethod extends Method { */ class HttpServletRequestGetRequestURIMethod extends Method { HttpServletRequestGetRequestURIMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getRequestURI") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getRequestURI") and + this.getNumberOfParameters() = 0 } } @@ -144,9 +144,9 @@ class HttpServletRequestGetRequestURIMethod extends Method { */ library class HttpServletRequestGetRemoteUserMethod extends Method { HttpServletRequestGetRemoteUserMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getRemoteUser") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getRemoteUser") and + this.getNumberOfParameters() = 0 } } @@ -155,8 +155,8 @@ library class HttpServletRequestGetRemoteUserMethod extends Method { */ library class ServletRequestGetBodyMethod extends Method { ServletRequestGetBodyMethod() { - getDeclaringType() instanceof ServletRequest and - (hasName("getInputStream") or hasName("getReader")) + this.getDeclaringType() instanceof ServletRequest and + (this.hasName("getInputStream") or this.hasName("getReader")) } } @@ -166,7 +166,7 @@ library class ServletRequestGetBodyMethod extends Method { */ class ServletResponse extends RefType { ServletResponse() { - hasQualifiedName("javax.servlet", "ServletResponse") or + this.hasQualifiedName("javax.servlet", "ServletResponse") or this instanceof HttpServletResponse } } @@ -175,7 +175,7 @@ class ServletResponse extends RefType { * The interface `javax.servlet.http.HttpServletResponse`. */ class HttpServletResponse extends RefType { - HttpServletResponse() { hasQualifiedName("javax.servlet.http", "HttpServletResponse") } + HttpServletResponse() { this.hasQualifiedName("javax.servlet.http", "HttpServletResponse") } } /** @@ -183,11 +183,11 @@ class HttpServletResponse extends RefType { */ class HttpServletResponseSendErrorMethod extends Method { HttpServletResponseSendErrorMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("sendError") and - getNumberOfParameters() = 2 and - getParameter(0).getType().hasName("int") and - getParameter(1).getType() instanceof TypeString + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("sendError") and + this.getNumberOfParameters() = 2 and + this.getParameter(0).getType().hasName("int") and + this.getParameter(1).getType() instanceof TypeString } } @@ -196,8 +196,8 @@ class HttpServletResponseSendErrorMethod extends Method { */ class ServletRequestGetRequestDispatcherMethod extends Method { ServletRequestGetRequestDispatcherMethod() { - getDeclaringType() instanceof ServletRequest and - hasName("getRequestDispatcher") + this.getDeclaringType() instanceof ServletRequest and + this.hasName("getRequestDispatcher") } } @@ -206,10 +206,10 @@ class ServletRequestGetRequestDispatcherMethod extends Method { */ class HttpServletResponseSendRedirectMethod extends Method { HttpServletResponseSendRedirectMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("sendRedirect") and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("sendRedirect") and + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof TypeString } } @@ -218,9 +218,9 @@ class HttpServletResponseSendRedirectMethod extends Method { */ class ServletResponseGetWriterMethod extends Method { ServletResponseGetWriterMethod() { - getDeclaringType() instanceof ServletResponse and - hasName("getWriter") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof ServletResponse and + this.hasName("getWriter") and + this.getNumberOfParameters() = 0 } } @@ -229,15 +229,15 @@ class ServletResponseGetWriterMethod extends Method { */ class ServletResponseGetOutputStreamMethod extends Method { ServletResponseGetOutputStreamMethod() { - getDeclaringType() instanceof ServletResponse and - hasName("getOutputStream") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof ServletResponse and + this.hasName("getOutputStream") and + this.getNumberOfParameters() = 0 } } /** The class `javax.servlet.http.Cookie`. */ library class TypeCookie extends Class { - TypeCookie() { hasQualifiedName("javax.servlet.http", "Cookie") } + TypeCookie() { this.hasQualifiedName("javax.servlet.http", "Cookie") } } /** @@ -245,9 +245,9 @@ library class TypeCookie extends Class { */ library class CookieGetValueMethod extends Method { CookieGetValueMethod() { - getDeclaringType() instanceof TypeCookie and - hasName("getValue") and - getReturnType() instanceof TypeString + this.getDeclaringType() instanceof TypeCookie and + this.hasName("getValue") and + this.getReturnType() instanceof TypeString } } @@ -256,10 +256,10 @@ library class CookieGetValueMethod extends Method { */ library class CookieGetNameMethod extends Method { CookieGetNameMethod() { - getDeclaringType() instanceof TypeCookie and - hasName("getName") and - getReturnType() instanceof TypeString and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof TypeCookie and + this.hasName("getName") and + this.getReturnType() instanceof TypeString and + this.getNumberOfParameters() = 0 } } @@ -268,10 +268,10 @@ library class CookieGetNameMethod extends Method { */ library class CookieGetCommentMethod extends Method { CookieGetCommentMethod() { - getDeclaringType() instanceof TypeCookie and - hasName("getComment") and - getReturnType() instanceof TypeString and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof TypeCookie and + this.hasName("getComment") and + this.getReturnType() instanceof TypeString and + this.getNumberOfParameters() = 0 } } @@ -280,8 +280,8 @@ library class CookieGetCommentMethod extends Method { */ class ResponseAddCookieMethod extends Method { ResponseAddCookieMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("addCookie") + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("addCookie") } } @@ -290,8 +290,8 @@ class ResponseAddCookieMethod extends Method { */ class ResponseAddHeaderMethod extends Method { ResponseAddHeaderMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("addHeader") + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("addHeader") } } @@ -300,8 +300,8 @@ class ResponseAddHeaderMethod extends Method { */ class ResponseSetHeaderMethod extends Method { ResponseSetHeaderMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("setHeader") + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("setHeader") } } @@ -309,7 +309,7 @@ class ResponseSetHeaderMethod extends Method { * A class that has `javax.servlet.Servlet` as an ancestor. */ class ServletClass extends Class { - ServletClass() { getAnAncestor().hasQualifiedName("javax.servlet", "Servlet") } + ServletClass() { this.getAnAncestor().hasQualifiedName("javax.servlet", "Servlet") } } /** @@ -320,13 +320,13 @@ class ServletClass extends Class { */ class ServletWebXMLListenerType extends RefType { ServletWebXMLListenerType() { - hasQualifiedName("javax.servlet", "ServletContextAttributeListener") or - hasQualifiedName("javax.servlet", "ServletContextListener") or - hasQualifiedName("javax.servlet", "ServletRequestAttributeListener") or - hasQualifiedName("javax.servlet", "ServletRequestListener") or - hasQualifiedName("javax.servlet.http", "HttpSessionAttributeListener") or - hasQualifiedName("javax.servlet.http", "HttpSessionIdListener") or - hasQualifiedName("javax.servlet.http", "HttpSessionListener") + this.hasQualifiedName("javax.servlet", "ServletContextAttributeListener") or + this.hasQualifiedName("javax.servlet", "ServletContextListener") or + this.hasQualifiedName("javax.servlet", "ServletRequestAttributeListener") or + this.hasQualifiedName("javax.servlet", "ServletRequestListener") or + this.hasQualifiedName("javax.servlet.http", "HttpSessionAttributeListener") or + this.hasQualifiedName("javax.servlet.http", "HttpSessionIdListener") or + this.hasQualifiedName("javax.servlet.http", "HttpSessionListener") // Listeners that are not configured in `web.xml`: // - `HttpSessionActivationListener` // - `HttpSessionBindingListener` diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index 513c4c0099c..01d73c031fc 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -151,8 +151,8 @@ class SslUnwrapMethod extends Method { /** The `getSession` method of the class `javax.net.ssl.SSLSession`.select */ class GetSslSessionMethod extends Method { GetSslSessionMethod() { - hasName("getSession") and - getDeclaringType().getASupertype*() instanceof SSLSession + this.hasName("getSession") and + this.getDeclaringType().getASupertype*() instanceof SSLSession } } diff --git a/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll b/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll index 5f4d85fe22b..5eff757a93d 100644 --- a/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll +++ b/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll @@ -112,5 +112,5 @@ class MyBatisMapperInclude extends MyBatisMapperXMLElement { * A `` element in a `MyBatisMapperXMLElement`. */ class MyBatisMapperForeach extends MyBatisMapperXMLElement { - MyBatisMapperForeach() { getName() = "foreach" } + MyBatisMapperForeach() { this.getName() = "foreach" } } diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index cd465121cb7..57dcf6f2eec 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -998,7 +998,7 @@ module API { * Gets an API node where a RHS of the node is the `i`th argument to this call. */ pragma[noinline] - private Node getAParameterCandidate(int i) { result.getARhs() = getArgument(i) } + private Node getAParameterCandidate(int i) { result.getARhs() = this.getArgument(i) } /** Gets the API node for a parameter of this invocation. */ Node getAParameter() { result = this.getParameter(_) } diff --git a/javascript/ql/lib/semmle/javascript/Routing.qll b/javascript/ql/lib/semmle/javascript/Routing.qll index 59fc0a814e4..61300f11a42 100644 --- a/javascript/ql/lib/semmle/javascript/Routing.qll +++ b/javascript/ql/lib/semmle/javascript/Routing.qll @@ -137,12 +137,12 @@ module Routing { * this subtree, and subsequently passed on to the successor. */ predicate mayResumeDispatch() { - getLastChild().mayResumeDispatch() + this.getLastChild().mayResumeDispatch() or exists(this.(RouteHandler).getAContinuationInvocation()) or // Leaf nodes that aren't functions are assumed to invoke their continuation - not exists(getLastChild()) and + not exists(this.getLastChild()) and not this instanceof RouteHandler or this instanceof MkRouter @@ -150,7 +150,7 @@ module Routing { /** Gets the parent of this node, provided that this node may invoke its continuation. */ private Node getContinuationParent() { - result = getParent() and + result = this.getParent() and result.mayResumeDispatch() } @@ -170,7 +170,7 @@ module Routing { */ private predicate isFork() { exists(Node child | - child = getAChild() and + child = this.getAChild() and child.mayResumeDispatch() and exists(child.getNextSibling()) ) @@ -184,11 +184,11 @@ module Routing { * that is, a node that has siblings (i.e. multiple children). */ private string getPathFromFork(Node fork) { - isFork() and + this.isFork() and this = fork and result = "" or - exists(Node parent | parent = getParent() | + exists(Node parent | parent = this.getParent() | not exists(parent.getRelativePath()) and result = parent.getPathFromFork(fork) or @@ -205,27 +205,27 @@ module Routing { * that is, a node that has siblings (i.e. multiple children). */ private string getHttpMethodFromFork(Node fork) { - isFork() and + this.isFork() and this = fork and ( - result = getOwnHttpMethod() + result = this.getOwnHttpMethod() or - not exists(getOwnHttpMethod()) and + not exists(this.getOwnHttpMethod()) and result = "*" ) or - result = getParent().getHttpMethodFromFork(fork) and + result = this.getParent().getHttpMethodFromFork(fork) and ( // Only the ancestor restricts the HTTP method - not exists(getOwnHttpMethod()) + not exists(this.getOwnHttpMethod()) or // Intersect permitted HTTP methods - result = getOwnHttpMethod() + result = this.getOwnHttpMethod() ) or // The ancestor allows any HTTP method, but this node restricts it - getParent().getHttpMethodFromFork(fork) = "*" and - result = getOwnHttpMethod() + this.getParent().getHttpMethodFromFork(fork) = "*" and + result = this.getOwnHttpMethod() } /** @@ -256,13 +256,15 @@ module Routing { * Holds if `node` has processed the incoming request strictly prior to this node. */ pragma[inline] - predicate isGuardedByNode(Node node) { isGuardedByNodeInternal(pragma[only_bind_out](node)) } + predicate isGuardedByNode(Node node) { + this.isGuardedByNodeInternal(pragma[only_bind_out](node)) + } /** * Holds if the middleware corresponding to `node` has processed the incoming request strictly prior to this node. */ pragma[inline] - predicate isGuardedBy(DataFlow::Node node) { isGuardedByNode(getNode(node)) } + predicate isGuardedBy(DataFlow::Node node) { this.isGuardedByNode(getNode(node)) } /** * Gets an HTTP method name which this node will accept, or nothing if the node accepts all HTTP methods, not @@ -271,16 +273,16 @@ module Routing { HTTP::RequestMethodName getOwnHttpMethod() { none() } // Overridden in subclass private Node getAUseSiteInRouteSetup() { - if getParent() instanceof RouteSetup + if this.getParent() instanceof RouteSetup then result = this - else result = getParent().getAUseSiteInRouteSetup() + else result = this.getParent().getAUseSiteInRouteSetup() } /** Gets a place where this route node is installed as a route handler. */ Node getRouteInstallation() { - result = getAUseSiteInRouteSetup() + result = this.getAUseSiteInRouteSetup() or - not exists(getAUseSiteInRouteSetup()) and + not exists(this.getAUseSiteInRouteSetup()) and result = this } @@ -352,7 +354,7 @@ module Routing { Node getChild(int n) { none() } /** Gets the number of children of this route node. */ - final int getNumChild() { result = count(int n | exists(getChild(n))) } + final int getNumChild() { result = count(int n | exists(this.getChild(n))) } /** * Gets a path prefix to be matched against the path of incoming requests. @@ -416,7 +418,7 @@ module Routing { * Gets a data flow node that flows to this use-site in one step. */ DataFlow::Node getSource() { - result = getALocalSource() + result = this.getALocalSource() or StepSummary::smallstep(result, this, routeStepSummary()) or @@ -425,7 +427,7 @@ module Routing { RouteHandlerTrackingStep::step(result, this) or exists(string prop | - StepSummary::smallstep(result, getSourceProp(prop).getALocalUse(), StoreStep(prop)) + StepSummary::smallstep(result, this.getSourceProp(prop).getALocalUse(), StoreStep(prop)) ) or this = getAnEnumeratedArrayElement(result) @@ -435,32 +437,32 @@ module Routing { private DataFlow::SourceNode getSourceProp(string prop) { StepSummary::step(result, this, LoadStep(prop)) or - StepSummary::step(result, getSourceProp(prop), routeStepSummary()) + StepSummary::step(result, this.getSourceProp(prop), routeStepSummary()) or - StepSummary::step(result, getSourceProp(prop), CopyStep(prop)) + StepSummary::step(result, this.getSourceProp(prop), CopyStep(prop)) or exists(string oldProp | - StepSummary::step(result, getSourceProp(oldProp), LoadStoreStep(prop, oldProp)) + StepSummary::step(result, this.getSourceProp(oldProp), LoadStoreStep(prop, oldProp)) ) } private DataFlow::Node getStrictSource() { - result = getSource() and + result = this.getSource() and result != this } final override Routing::Node getChild(int n) { n = 0 and - result = MkValueNode(getStrictSource()) + result = MkValueNode(this.getStrictSource()) or // If we cannot find the source of the use-site, but we know it's somehow a reference to a router, // treat the router as the source. This is needed to handle chaining calls on the router, as the // specific framework model knows about chaining steps, but the general `getSource()` predicate doesn't. n = 0 and - not exists(getStrictSource()) and + not exists(this.getStrictSource()) and exists(Router::Range router | this = router.getAReference().getALocalUse() and - result = MkRouter(router, getContainer()) + result = MkRouter(router, this.getContainer()) ) } } @@ -483,7 +485,7 @@ module Routing { */ abstract DataFlow::Node getArgumentNode(int n); - final override Node getChild(int n) { result = MkValueNode(getArgumentNode(n)) } + final override Node getChild(int n) { result = MkValueNode(this.getArgumentNode(n)) } } /** An argument to a `WithArguments` instance, seen as a use site. */ @@ -497,7 +499,7 @@ module Routing { private class ImpliedArrayRoute extends ValueNode::WithArguments, DataFlow::ArrayCreationNode { ImpliedArrayRoute() { this instanceof ValueNode::UseSite } - override DataFlow::Node getArgumentNode(int n) { result = getElement(n) } + override DataFlow::Node getArgumentNode(int n) { result = this.getElement(n) } } } @@ -521,10 +523,10 @@ module Routing { * A node in the routing tree which has no parent. */ class RootNode extends Node { - RootNode() { not exists(getParent()) } + RootNode() { not exists(this.getParent()) } /** Gets a node that is part of this subtree. */ - final Node getADescendant() { result = getAChild*() } + final Node getADescendant() { result = this.getAChild*() } } /** @@ -546,7 +548,7 @@ module Routing { * * This is an alias for `getParent`, but may be preferred for readability. */ - final Node getRouter() { result = getParent() } + final Node getRouter() { result = this.getParent() } } /** @@ -568,7 +570,7 @@ module Routing { Node getChild(int n) { none() } /** Gets the number of children of this route node. */ - final int getNumChild() { result = count(int n | exists(getChild(n))) } + final int getNumChild() { result = count(int n | exists(this.getChild(n))) } /** * Gets a path prefix to be matched against the path of incoming requests. @@ -630,13 +632,13 @@ module Routing { * This class can be extended to contribute new kinds of route handlers. */ abstract class MethodCall extends RouteSetup::Range, DataFlow::MethodCallNode { - override Node getChild(int n) { result = MkValueNode(getChildNode(n)) } + override Node getChild(int n) { result = MkValueNode(this.getChildNode(n)) } /** Gets the `n`th child of this route setup. */ - DataFlow::Node getChildNode(int n) { result = getArgument(n) } + DataFlow::Node getChildNode(int n) { result = this.getArgument(n) } override predicate isInstalledAt(Router::Range router, ControlFlowNode cfgNode) { - this = router.getAReference().getAMethodCall() and cfgNode = getEnclosingExpr() + this = router.getAReference().getAMethodCall() and cfgNode = this.getEnclosingExpr() } } @@ -679,14 +681,14 @@ module Routing { result.isInstalledAt(router, any(ControlFlowNode cfg | cfg.getContainer() = container)) } - override Node getAChild() { result = MkRouteSetup(getARouteSetup()) } + override Node getAChild() { result = MkRouteSetup(this.getARouteSetup()) } override Node getLastChild() { result = getMostRecentRouteSetupAt(router, container.getExit()) } override Node getFirstChild() { - result = getAChild() and not exists(result.getPreviousSibling()) + result = this.getAChild() and not exists(result.getPreviousSibling()) } } } @@ -753,14 +755,14 @@ module Routing { ImpliedRouteSetup() { FlowSteps::calls(this, target) and routerIsLiveInContainer(router, target) and - routerIsLiveInContainer(router, getContainer()) + routerIsLiveInContainer(router, this.getContainer()) } override Routing::Node getChild(int n) { result = MkRouter(router, target) and n = 0 } override predicate isInstalledAt(Router::Range r, ControlFlowNode cfgNode) { r = router and - cfgNode = getEnclosingExpr() + cfgNode = this.getEnclosingExpr() } } @@ -799,11 +801,11 @@ module Routing { * if the default behavior is inadequate for that framework. */ DataFlow::CallNode getAContinuationInvocation() { - result = getAParameter().ref().getAnInvocation() and + result = this.getAParameter().ref().getAnInvocation() and result.getNumArgument() = 0 or result.(DataFlow::MethodCallNode).getMethodName() = "then" and - result.getArgument(0) = getAParameter().ref().getALocalUse() + result.getArgument(0) = this.getAParameter().ref().getALocalUse() } } @@ -827,11 +829,11 @@ module Routing { t.start() and result = this or - exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) + exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t)) } /** Gets a data flow node referring to this route handler parameter. */ - DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } + DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) } /** * Gets the corresponding route handler, that is, the function on which this is a parameter. diff --git a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll index 1d28a29df8f..0eed07a6962 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll @@ -75,7 +75,9 @@ abstract class FrameworkLibraryInstance extends TopLevel { * via the `src` attribute of a `