mirror of
https://github.com/github/codeql.git
synced 2026-01-03 09:40:17 +01:00
Merge branch 'main' into goTiming
This commit is contained in:
@@ -15030,25 +15030,28 @@ ir.cpp:
|
||||
# 1999| Value = [Literal] 5
|
||||
# 1999| ValueCategory = prvalue
|
||||
# 2000| getStmt(3): [ExprStmt] ExprStmt
|
||||
# 2000| getExpr(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2000| getExpr(): [AssignExpr] ... = ...
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getCondition(): [VariableAccess] a
|
||||
# 2000| Type = [BoolType] bool
|
||||
# 2000| ValueCategory = prvalue(load)
|
||||
# 2000| getThen(): [VariableAccess] x
|
||||
# 2000| getLValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getElse(): [AssignExpr] ... = ...
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getLValue(): [VariableAccess] y
|
||||
# 2000| getCondition(): [VariableAccess] a
|
||||
# 2000| Type = [BoolType] bool
|
||||
# 2000| ValueCategory = prvalue(load)
|
||||
# 2000| getThen(): [VariableAccess] x
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getRValue(): [Literal] 7
|
||||
# 2000| getElse(): [VariableAccess] y
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| Value = [Literal] 7
|
||||
# 2000| ValueCategory = prvalue
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getRValue(): [Literal] 7
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| Value = [Literal] 7
|
||||
# 2000| ValueCategory = prvalue
|
||||
# 2000| getLValue().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2001| getStmt(4): [ReturnStmt] return ...
|
||||
# 2003| [CopyAssignmentOperator] TernaryPodObj& TernaryPodObj::operator=(TernaryPodObj const&)
|
||||
# 2003| <params>:
|
||||
@@ -15151,31 +15154,34 @@ ir.cpp:
|
||||
# 2010| getExpr(): [AssignExpr] ... = ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getLValue(): [VariableAccess] z
|
||||
# 2010| getLValue(): [AssignExpr] ... = ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getCondition(): [VariableAccess] a
|
||||
# 2010| Type = [BoolType] bool
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getThen(): [VariableAccess] x
|
||||
# 2010| getLValue(): [VariableAccess] z
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getElse(): [AssignExpr] ... = ...
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getLValue(): [VariableAccess] y
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue(): [Literal] 0
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| Value = [Literal] 0
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2010| getCondition(): [VariableAccess] a
|
||||
# 2010| Type = [BoolType] bool
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getThen(): [VariableAccess] x
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getElse(): [VariableAccess] y
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getRValue(): [Literal] 0
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| Value = [Literal] 0
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getLValue().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2011| getStmt(4): [ReturnStmt] return ...
|
||||
# 2013| [CopyAssignmentOperator] TernaryNonPodObj& TernaryNonPodObj::operator=(TernaryNonPodObj const&)
|
||||
# 2013| <params>:
|
||||
@@ -15339,38 +15345,38 @@ ir.cpp:
|
||||
# 2021| getExpr(): [FunctionCall] call to operator=
|
||||
# 2021| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier(): [VariableAccess] z
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0): [ConditionalExpr] ... ? ... : ...
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getCondition(): [VariableAccess] a
|
||||
# 2021| Type = [BoolType] bool
|
||||
# 2021| ValueCategory = prvalue(load)
|
||||
# 2021| getThen(): [VariableAccess] x
|
||||
# 2021| getQualifier(): [FunctionCall] call to operator=
|
||||
# 2021| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier(): [VariableAccess] z
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getElse(): [FunctionCall] call to operator=
|
||||
# 2021| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier(): [VariableAccess] y
|
||||
# 2021| getArgument(0): [ConditionalExpr] ... ? ... : ...
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getCondition(): [VariableAccess] a
|
||||
# 2021| Type = [BoolType] bool
|
||||
# 2021| ValueCategory = prvalue(load)
|
||||
# 2021| getThen(): [VariableAccess] x
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2021| Type = [VoidType] void
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2021| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2021| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2021| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr(): [TemporaryObjectExpr] temporary object
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getElse().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2021| getElse(): [VariableAccess] y
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2021| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2021| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2021| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2021| Type = [VoidType] void
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
@@ -15380,6 +15386,9 @@ ir.cpp:
|
||||
# 2021| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2021| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr(): [TemporaryObjectExpr] temporary object
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
|
||||
@@ -1997,7 +1997,7 @@ void TernaryTestInt(bool a, int x, int y, int z) {
|
||||
z = a ? x : y;
|
||||
z = a ? x : 5;
|
||||
z = a ? 3 : 5;
|
||||
a ? x : y = 7;
|
||||
(a ? x : y) = 7;
|
||||
}
|
||||
|
||||
struct TernaryPodObj {
|
||||
@@ -2007,7 +2007,7 @@ void TernaryTestPodObj(bool a, TernaryPodObj x, TernaryPodObj y, TernaryPodObj z
|
||||
z = a ? x : y;
|
||||
z = a ? x : TernaryPodObj();
|
||||
z = a ? TernaryPodObj() : TernaryPodObj();
|
||||
z = a ? x : y = TernaryPodObj();
|
||||
(z = a ? x : y) = TernaryPodObj();
|
||||
}
|
||||
|
||||
struct TernaryNonPodObj {
|
||||
@@ -2018,7 +2018,7 @@ void TernaryTestNonPodObj(bool a, TernaryNonPodObj x, TernaryNonPodObj y, Ternar
|
||||
z = a ? x : y;
|
||||
z = a ? x : TernaryNonPodObj();
|
||||
z = a ? TernaryNonPodObj() : TernaryNonPodObj();
|
||||
z = a ? x : y = TernaryNonPodObj();
|
||||
(z = a ? x : y) = TernaryNonPodObj();
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -9078,7 +9078,7 @@
|
||||
| ir.cpp:1993:13:1993:32 | StoreValue | r1993_2 |
|
||||
| ir.cpp:1996:6:1996:19 | ChiPartial | partial:m1996_3 |
|
||||
| ir.cpp:1996:6:1996:19 | ChiTotal | total:m1996_2 |
|
||||
| ir.cpp:1996:6:1996:19 | SideEffect | m1996_3 |
|
||||
| ir.cpp:1996:6:1996:19 | SideEffect | ~m2000_9 |
|
||||
| ir.cpp:1996:26:1996:26 | Address | &:r1996_5 |
|
||||
| ir.cpp:1996:33:1996:33 | Address | &:r1996_7 |
|
||||
| ir.cpp:1996:40:1996:40 | Address | &:r1996_9 |
|
||||
@@ -9128,20 +9128,21 @@
|
||||
| ir.cpp:1999:9:1999:17 | StoreValue | r1999_6 |
|
||||
| ir.cpp:1999:13:1999:13 | StoreValue | r1999_9 |
|
||||
| ir.cpp:1999:17:1999:17 | StoreValue | r1999_12 |
|
||||
| ir.cpp:2000:5:2000:5 | Address | &:r2000_1 |
|
||||
| ir.cpp:2000:5:2000:5 | Condition | r2000_2 |
|
||||
| ir.cpp:2000:5:2000:5 | Load | m1996_6 |
|
||||
| ir.cpp:2000:5:2000:17 | Address | &:r2000_5 |
|
||||
| ir.cpp:2000:5:2000:17 | Address | &:r2000_8 |
|
||||
| ir.cpp:2000:5:2000:17 | Address | &:r2000_14 |
|
||||
| ir.cpp:2000:5:2000:17 | Load | m2000_4 |
|
||||
| ir.cpp:2000:5:2000:17 | Phi | from 11:m2000_9 |
|
||||
| ir.cpp:2000:5:2000:17 | Phi | from 12:m2000_15 |
|
||||
| ir.cpp:2000:9:2000:9 | StoreValue | r2000_7 |
|
||||
| ir.cpp:2000:13:2000:13 | Address | &:r2000_11 |
|
||||
| ir.cpp:2000:13:2000:13 | Unary | r2000_11 |
|
||||
| ir.cpp:2000:13:2000:17 | StoreValue | r2000_13 |
|
||||
| ir.cpp:2000:17:2000:17 | StoreValue | r2000_10 |
|
||||
| ir.cpp:2000:5:2000:19 | ChiPartial | partial:m2000_8 |
|
||||
| ir.cpp:2000:5:2000:19 | ChiTotal | total:m1996_4 |
|
||||
| ir.cpp:2000:6:2000:6 | Address | &:r2000_2 |
|
||||
| ir.cpp:2000:6:2000:6 | Condition | r2000_3 |
|
||||
| ir.cpp:2000:6:2000:6 | Load | m1996_6 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_6 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_7 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_11 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_14 |
|
||||
| ir.cpp:2000:6:2000:14 | Load | m2000_5 |
|
||||
| ir.cpp:2000:6:2000:14 | Phi | from 11:m2000_12 |
|
||||
| ir.cpp:2000:6:2000:14 | Phi | from 12:m2000_15 |
|
||||
| ir.cpp:2000:10:2000:10 | StoreValue | r2000_10 |
|
||||
| ir.cpp:2000:14:2000:14 | StoreValue | r2000_13 |
|
||||
| ir.cpp:2000:19:2000:19 | StoreValue | r2000_1 |
|
||||
| ir.cpp:2006:6:2006:22 | ChiPartial | partial:m2006_3 |
|
||||
| ir.cpp:2006:6:2006:22 | ChiTotal | total:m2006_2 |
|
||||
| ir.cpp:2006:6:2006:22 | SideEffect | m2006_3 |
|
||||
@@ -9218,28 +9219,30 @@
|
||||
| ir.cpp:2009:31:2009:45 | Load | m2009_20 |
|
||||
| ir.cpp:2009:31:2009:45 | StoreValue | r2009_19 |
|
||||
| ir.cpp:2009:31:2009:45 | StoreValue | r2009_21 |
|
||||
| ir.cpp:2010:5:2010:5 | Address | &:r2010_7 |
|
||||
| ir.cpp:2010:9:2010:9 | Address | &:r2010_1 |
|
||||
| ir.cpp:2010:9:2010:9 | Condition | r2010_2 |
|
||||
| ir.cpp:2010:9:2010:9 | Load | m2006_6 |
|
||||
| ir.cpp:2010:9:2010:35 | Address | &:r2010_5 |
|
||||
| ir.cpp:2010:9:2010:35 | Address | &:r2010_11 |
|
||||
| ir.cpp:2010:9:2010:35 | Address | &:r2010_20 |
|
||||
| ir.cpp:2010:9:2010:35 | Load | m2010_4 |
|
||||
| ir.cpp:2010:9:2010:35 | Phi | from 11:m2010_12 |
|
||||
| ir.cpp:2010:9:2010:35 | Phi | from 12:m2010_21 |
|
||||
| ir.cpp:2010:9:2010:35 | StoreValue | r2010_6 |
|
||||
| ir.cpp:2010:13:2010:13 | Address | &:r2010_9 |
|
||||
| ir.cpp:2010:13:2010:13 | Load | m2006_8 |
|
||||
| ir.cpp:2010:13:2010:13 | StoreValue | r2010_10 |
|
||||
| ir.cpp:2010:17:2010:17 | Address | &:r2010_17 |
|
||||
| ir.cpp:2010:17:2010:35 | StoreValue | r2010_19 |
|
||||
| ir.cpp:2010:21:2010:35 | Address | &:r2010_13 |
|
||||
| ir.cpp:2010:21:2010:35 | Address | &:r2010_13 |
|
||||
| ir.cpp:2010:21:2010:35 | Load | m2010_15 |
|
||||
| ir.cpp:2010:21:2010:35 | StoreValue | r2010_14 |
|
||||
| ir.cpp:2010:21:2010:35 | StoreValue | r2010_16 |
|
||||
| ir.cpp:2010:21:2010:35 | Unary | r2010_16 |
|
||||
| ir.cpp:2010:6:2010:6 | Address | &:r2010_11 |
|
||||
| ir.cpp:2010:6:2010:6 | Unary | r2010_11 |
|
||||
| ir.cpp:2010:6:2010:18 | Address | &:r2010_13 |
|
||||
| ir.cpp:2010:10:2010:10 | Address | &:r2010_5 |
|
||||
| ir.cpp:2010:10:2010:10 | Condition | r2010_6 |
|
||||
| ir.cpp:2010:10:2010:10 | Load | m2006_6 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_9 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_17 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_21 |
|
||||
| ir.cpp:2010:10:2010:18 | Load | m2010_8 |
|
||||
| ir.cpp:2010:10:2010:18 | Phi | from 11:m2010_18 |
|
||||
| ir.cpp:2010:10:2010:18 | Phi | from 12:m2010_22 |
|
||||
| ir.cpp:2010:10:2010:18 | StoreValue | r2010_10 |
|
||||
| ir.cpp:2010:14:2010:14 | Address | &:r2010_15 |
|
||||
| ir.cpp:2010:14:2010:14 | Load | m2006_8 |
|
||||
| ir.cpp:2010:14:2010:14 | StoreValue | r2010_16 |
|
||||
| ir.cpp:2010:18:2010:18 | Address | &:r2010_19 |
|
||||
| ir.cpp:2010:18:2010:18 | Load | m2006_10 |
|
||||
| ir.cpp:2010:18:2010:18 | StoreValue | r2010_20 |
|
||||
| ir.cpp:2010:23:2010:37 | Address | &:r2010_1 |
|
||||
| ir.cpp:2010:23:2010:37 | Address | &:r2010_1 |
|
||||
| ir.cpp:2010:23:2010:37 | Load | m2010_3 |
|
||||
| ir.cpp:2010:23:2010:37 | StoreValue | r2010_2 |
|
||||
| ir.cpp:2010:23:2010:37 | StoreValue | r2010_4 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
@@ -9280,7 +9283,7 @@
|
||||
| ir.cpp:2014:13:2014:29 | SideEffect | m2014_8 |
|
||||
| ir.cpp:2017:6:2017:25 | ChiPartial | partial:m2017_3 |
|
||||
| ir.cpp:2017:6:2017:25 | ChiTotal | total:m2017_2 |
|
||||
| ir.cpp:2017:6:2017:25 | SideEffect | ~m2021_14 |
|
||||
| ir.cpp:2017:6:2017:25 | SideEffect | ~m2021_32 |
|
||||
| ir.cpp:2017:32:2017:32 | Address | &:r2017_5 |
|
||||
| ir.cpp:2017:52:2017:52 | Address | &:r2017_7 |
|
||||
| ir.cpp:2017:72:2017:72 | Address | &:r2017_9 |
|
||||
@@ -9423,60 +9426,58 @@
|
||||
| ir.cpp:2020:34:2020:51 | Load | m2020_40 |
|
||||
| ir.cpp:2020:34:2020:51 | SideEffect | ~m2019_16 |
|
||||
| ir.cpp:2020:34:2020:51 | StoreValue | r2020_41 |
|
||||
| ir.cpp:2021:5:2021:5 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:5:2021:5 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:5:2021:5 | Arg(this) | this:r2021_1 |
|
||||
| ir.cpp:2021:5:2021:5 | ChiPartial | partial:m2021_17 |
|
||||
| ir.cpp:2021:5:2021:5 | ChiTotal | total:m2020_20 |
|
||||
| ir.cpp:2021:5:2021:5 | SideEffect | m2020_20 |
|
||||
| ir.cpp:2021:7:2021:7 | CallTarget | func:r2021_2 |
|
||||
| ir.cpp:2021:7:2021:7 | ChiPartial | partial:m2021_13 |
|
||||
| ir.cpp:2021:7:2021:7 | ChiTotal | total:m2021_6 |
|
||||
| ir.cpp:2021:7:2021:7 | SideEffect | ~m2021_6 |
|
||||
| ir.cpp:2021:7:2021:7 | Unary | r2021_12 |
|
||||
| ir.cpp:2021:9:2021:9 | Address | &:r2021_3 |
|
||||
| ir.cpp:2021:9:2021:9 | Condition | r2021_4 |
|
||||
| ir.cpp:2021:9:2021:9 | Load | m2017_6 |
|
||||
| ir.cpp:2021:9:2021:38 | Address | &:r2021_8 |
|
||||
| ir.cpp:2021:9:2021:38 | Address | &:r2021_11 |
|
||||
| ir.cpp:2021:9:2021:38 | Address | &:r2021_21 |
|
||||
| ir.cpp:2021:9:2021:38 | Address | &:r2021_43 |
|
||||
| ir.cpp:2021:9:2021:38 | Arg(0) | 0:r2021_11 |
|
||||
| ir.cpp:2021:9:2021:38 | Load | m2021_7 |
|
||||
| ir.cpp:2021:9:2021:38 | Phi | from 11:m2021_22 |
|
||||
| ir.cpp:2021:9:2021:38 | Phi | from 11:~m2020_16 |
|
||||
| ir.cpp:2021:9:2021:38 | Phi | from 12:m2021_44 |
|
||||
| ir.cpp:2021:9:2021:38 | Phi | from 12:~m2021_37 |
|
||||
| ir.cpp:2021:9:2021:38 | SideEffect | ~m2021_14 |
|
||||
| ir.cpp:2021:9:2021:38 | Unary | r2021_9 |
|
||||
| ir.cpp:2021:9:2021:38 | Unary | r2021_10 |
|
||||
| ir.cpp:2021:13:2021:13 | StoreValue | r2021_20 |
|
||||
| ir.cpp:2021:17:2021:17 | Address | &:r2021_23 |
|
||||
| ir.cpp:2021:17:2021:17 | Address | &:r2021_23 |
|
||||
| ir.cpp:2021:17:2021:17 | Arg(this) | this:r2021_23 |
|
||||
| ir.cpp:2021:17:2021:17 | ChiPartial | partial:m2021_40 |
|
||||
| ir.cpp:2021:17:2021:17 | ChiTotal | total:m2017_10 |
|
||||
| ir.cpp:2021:17:2021:17 | SideEffect | m2017_10 |
|
||||
| ir.cpp:2021:19:2021:19 | CallTarget | func:r2021_24 |
|
||||
| ir.cpp:2021:19:2021:19 | ChiPartial | partial:m2021_36 |
|
||||
| ir.cpp:2021:19:2021:19 | ChiTotal | total:m2021_30 |
|
||||
| ir.cpp:2021:19:2021:19 | SideEffect | ~m2021_30 |
|
||||
| ir.cpp:2021:19:2021:19 | Unary | r2021_35 |
|
||||
| ir.cpp:2021:19:2021:39 | StoreValue | r2021_42 |
|
||||
| ir.cpp:2021:21:2021:38 | Address | &:r2021_25 |
|
||||
| ir.cpp:2021:21:2021:38 | Address | &:r2021_25 |
|
||||
| ir.cpp:2021:21:2021:38 | Address | &:r2021_34 |
|
||||
| ir.cpp:2021:21:2021:38 | Arg(0) | 0:r2021_34 |
|
||||
| ir.cpp:2021:21:2021:38 | Arg(this) | this:r2021_25 |
|
||||
| ir.cpp:2021:21:2021:38 | CallTarget | func:r2021_27 |
|
||||
| ir.cpp:2021:21:2021:38 | ChiPartial | partial:m2021_29 |
|
||||
| ir.cpp:2021:21:2021:38 | ChiPartial | partial:m2021_31 |
|
||||
| ir.cpp:2021:21:2021:38 | ChiTotal | total:m2020_16 |
|
||||
| ir.cpp:2021:21:2021:38 | ChiTotal | total:m2021_26 |
|
||||
| ir.cpp:2021:21:2021:38 | SideEffect | ~m2020_16 |
|
||||
| ir.cpp:2021:21:2021:38 | SideEffect | ~m2021_32 |
|
||||
| ir.cpp:2021:21:2021:38 | Unary | r2021_25 |
|
||||
| ir.cpp:2021:21:2021:38 | Unary | r2021_33 |
|
||||
| ir.cpp:2021:5:2021:19 | ChiPartial | partial:m2021_35 |
|
||||
| ir.cpp:2021:5:2021:19 | ChiTotal | total:m2021_17 |
|
||||
| ir.cpp:2021:5:2021:19 | SideEffect | m2021_17 |
|
||||
| ir.cpp:2021:6:2021:6 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | Arg(this) | this:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | ChiPartial | partial:m2021_16 |
|
||||
| ir.cpp:2021:6:2021:6 | ChiTotal | total:m2020_20 |
|
||||
| ir.cpp:2021:6:2021:6 | SideEffect | m2020_20 |
|
||||
| ir.cpp:2021:8:2021:8 | CallTarget | func:r2021_2 |
|
||||
| ir.cpp:2021:8:2021:8 | ChiPartial | partial:m2021_12 |
|
||||
| ir.cpp:2021:8:2021:8 | ChiTotal | total:m2020_16 |
|
||||
| ir.cpp:2021:8:2021:8 | SideEffect | ~m2020_16 |
|
||||
| ir.cpp:2021:8:2021:8 | Unary | r2021_11 |
|
||||
| ir.cpp:2021:8:2021:19 | Address | &:r2021_18 |
|
||||
| ir.cpp:2021:8:2021:19 | Address | &:r2021_18 |
|
||||
| ir.cpp:2021:8:2021:19 | Arg(this) | this:r2021_18 |
|
||||
| ir.cpp:2021:10:2021:10 | Address | &:r2021_3 |
|
||||
| ir.cpp:2021:10:2021:10 | Condition | r2021_4 |
|
||||
| ir.cpp:2021:10:2021:10 | Load | m2017_6 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_7 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_10 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_39 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_42 |
|
||||
| ir.cpp:2021:10:2021:18 | Arg(0) | 0:r2021_10 |
|
||||
| ir.cpp:2021:10:2021:18 | Load | m2021_6 |
|
||||
| ir.cpp:2021:10:2021:18 | Phi | from 11:m2021_40 |
|
||||
| ir.cpp:2021:10:2021:18 | Phi | from 12:m2021_43 |
|
||||
| ir.cpp:2021:10:2021:18 | SideEffect | ~m2021_13 |
|
||||
| ir.cpp:2021:10:2021:18 | Unary | r2021_8 |
|
||||
| ir.cpp:2021:10:2021:18 | Unary | r2021_9 |
|
||||
| ir.cpp:2021:14:2021:14 | StoreValue | r2021_38 |
|
||||
| ir.cpp:2021:18:2021:18 | StoreValue | r2021_41 |
|
||||
| ir.cpp:2021:21:2021:21 | CallTarget | func:r2021_19 |
|
||||
| ir.cpp:2021:21:2021:21 | ChiPartial | partial:m2021_31 |
|
||||
| ir.cpp:2021:21:2021:21 | ChiTotal | total:m2021_25 |
|
||||
| ir.cpp:2021:21:2021:21 | SideEffect | ~m2021_25 |
|
||||
| ir.cpp:2021:21:2021:21 | Unary | r2021_30 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_29 |
|
||||
| ir.cpp:2021:23:2021:40 | Arg(0) | 0:r2021_29 |
|
||||
| ir.cpp:2021:23:2021:40 | Arg(this) | this:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | CallTarget | func:r2021_22 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiPartial | partial:m2021_24 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiPartial | partial:m2021_26 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiTotal | total:m2021_13 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiTotal | total:m2021_21 |
|
||||
| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_13 |
|
||||
| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_27 |
|
||||
| ir.cpp:2021:23:2021:40 | Unary | r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Unary | r2021_28 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |
|
||||
|
||||
@@ -10529,9 +10529,10 @@ ir.cpp:
|
||||
# 1999| r1999_5(int) = Load[#temp1999:9] : &:r1999_4, ~m?
|
||||
# 1999| r1999_6(glval<int>) = VariableAddress[z] :
|
||||
# 1999| mu1999_7(int) = Store[z] : &:r1999_6, r1999_5
|
||||
# 2000| r2000_1(glval<bool>) = VariableAddress[a] :
|
||||
# 2000| r2000_2(bool) = Load[a] : &:r2000_1, ~m?
|
||||
# 2000| v2000_3(void) = ConditionalBranch : r2000_2
|
||||
# 2000| r2000_1(int) = Constant[7] :
|
||||
# 2000| r2000_2(glval<bool>) = VariableAddress[a] :
|
||||
# 2000| r2000_3(bool) = Load[a] : &:r2000_2, ~m?
|
||||
# 2000| v2000_4(void) = ConditionalBranch : r2000_3
|
||||
#-----| False -> Block 12
|
||||
#-----| True -> Block 11
|
||||
|
||||
@@ -10548,26 +10549,24 @@ ir.cpp:
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2000| Block 10
|
||||
# 2000| r2000_4(glval<unknown>) = VariableAddress[#temp2000:5] :
|
||||
# 2000| r2000_5(glval<int>) = Load[#temp2000:5] : &:r2000_4, ~m?
|
||||
# 2000| r2000_5(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| r2000_6(glval<int>) = Load[#temp2000:6] : &:r2000_5, ~m?
|
||||
# 2000| mu2000_7(int) = Store[?] : &:r2000_6, r2000_1
|
||||
# 2001| v2001_1(void) = NoOp :
|
||||
# 1996| v1996_12(void) = ReturnVoid :
|
||||
# 1996| v1996_13(void) = AliasedUse : ~m?
|
||||
# 1996| v1996_14(void) = ExitFunction :
|
||||
|
||||
# 2000| Block 11
|
||||
# 2000| r2000_6(glval<int>) = VariableAddress[x] :
|
||||
# 2000| r2000_7(glval<unknown>) = VariableAddress[#temp2000:5] :
|
||||
# 2000| mu2000_8(glval<int>) = Store[#temp2000:5] : &:r2000_7, r2000_6
|
||||
# 2000| r2000_8(glval<int>) = VariableAddress[x] :
|
||||
# 2000| r2000_9(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| mu2000_10(glval<int>) = Store[#temp2000:6] : &:r2000_9, r2000_8
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2000| Block 12
|
||||
# 2000| r2000_9(int) = Constant[7] :
|
||||
# 2000| r2000_10(glval<int>) = VariableAddress[y] :
|
||||
# 2000| mu2000_11(int) = Store[y] : &:r2000_10, r2000_9
|
||||
# 2000| r2000_12(glval<int>) = CopyValue : r2000_10
|
||||
# 2000| r2000_13(glval<unknown>) = VariableAddress[#temp2000:5] :
|
||||
# 2000| mu2000_14(glval<int>) = Store[#temp2000:5] : &:r2000_13, r2000_12
|
||||
# 2000| r2000_11(glval<int>) = VariableAddress[y] :
|
||||
# 2000| r2000_12(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| mu2000_13(glval<int>) = Store[#temp2000:6] : &:r2000_12, r2000_11
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2006| void TernaryTestPodObj(bool, TernaryPodObj, TernaryPodObj, TernaryPodObj)
|
||||
@@ -10649,15 +10648,19 @@ ir.cpp:
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 2009| Block 7
|
||||
# 2009| r2009_5(glval<TernaryPodObj>) = VariableAddress[#temp2009:9] :
|
||||
# 2009| r2009_6(TernaryPodObj) = Load[#temp2009:9] : &:r2009_5, ~m?
|
||||
# 2009| mu2009_7(TernaryPodObj) = Store[#temp2009:9] : &:r2009_1, r2009_6
|
||||
# 2009| r2009_8(TernaryPodObj) = Load[#temp2009:9] : &:r2009_1, ~m?
|
||||
# 2009| r2009_9(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2009| mu2009_10(TernaryPodObj) = Store[z] : &:r2009_9, r2009_8
|
||||
# 2010| r2010_1(glval<bool>) = VariableAddress[a] :
|
||||
# 2010| r2010_2(bool) = Load[a] : &:r2010_1, ~m?
|
||||
# 2010| v2010_3(void) = ConditionalBranch : r2010_2
|
||||
# 2009| r2009_5(glval<TernaryPodObj>) = VariableAddress[#temp2009:9] :
|
||||
# 2009| r2009_6(TernaryPodObj) = Load[#temp2009:9] : &:r2009_5, ~m?
|
||||
# 2009| mu2009_7(TernaryPodObj) = Store[#temp2009:9] : &:r2009_1, r2009_6
|
||||
# 2009| r2009_8(TernaryPodObj) = Load[#temp2009:9] : &:r2009_1, ~m?
|
||||
# 2009| r2009_9(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2009| mu2009_10(TernaryPodObj) = Store[z] : &:r2009_9, r2009_8
|
||||
# 2010| r2010_1(glval<TernaryPodObj>) = VariableAddress[#temp2010:23] :
|
||||
# 2010| r2010_2(TernaryPodObj) = Constant[0] :
|
||||
# 2010| mu2010_3(TernaryPodObj) = Store[#temp2010:23] : &:r2010_1, r2010_2
|
||||
# 2010| r2010_4(TernaryPodObj) = Load[#temp2010:23] : &:r2010_1, ~m?
|
||||
# 2010| r2010_5(glval<bool>) = VariableAddress[a] :
|
||||
# 2010| r2010_6(bool) = Load[a] : &:r2010_5, ~m?
|
||||
# 2010| v2010_7(void) = ConditionalBranch : r2010_6
|
||||
#-----| False -> Block 12
|
||||
#-----| True -> Block 11
|
||||
|
||||
@@ -10680,32 +10683,29 @@ ir.cpp:
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2010| Block 10
|
||||
# 2010| r2010_4(glval<TernaryPodObj>) = VariableAddress[#temp2010:9] :
|
||||
# 2010| r2010_5(TernaryPodObj) = Load[#temp2010:9] : &:r2010_4, ~m?
|
||||
# 2010| r2010_6(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2010| mu2010_7(TernaryPodObj) = Store[z] : &:r2010_6, r2010_5
|
||||
# 2011| v2011_1(void) = NoOp :
|
||||
# 2006| v2006_12(void) = ReturnVoid :
|
||||
# 2006| v2006_13(void) = AliasedUse : ~m?
|
||||
# 2006| v2006_14(void) = ExitFunction :
|
||||
# 2010| r2010_8(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| r2010_9(TernaryPodObj) = Load[#temp2010:10] : &:r2010_8, ~m?
|
||||
# 2010| r2010_10(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2010| mu2010_11(TernaryPodObj) = Store[z] : &:r2010_10, r2010_9
|
||||
# 2010| r2010_12(glval<TernaryPodObj>) = CopyValue : r2010_10
|
||||
# 2010| mu2010_13(TernaryPodObj) = Store[?] : &:r2010_12, r2010_4
|
||||
# 2011| v2011_1(void) = NoOp :
|
||||
# 2006| v2006_12(void) = ReturnVoid :
|
||||
# 2006| v2006_13(void) = AliasedUse : ~m?
|
||||
# 2006| v2006_14(void) = ExitFunction :
|
||||
|
||||
# 2010| Block 11
|
||||
# 2010| r2010_8(glval<TernaryPodObj>) = VariableAddress[x] :
|
||||
# 2010| r2010_9(TernaryPodObj) = Load[x] : &:r2010_8, ~m?
|
||||
# 2010| r2010_10(glval<TernaryPodObj>) = VariableAddress[#temp2010:9] :
|
||||
# 2010| mu2010_11(TernaryPodObj) = Store[#temp2010:9] : &:r2010_10, r2010_9
|
||||
# 2010| r2010_14(glval<TernaryPodObj>) = VariableAddress[x] :
|
||||
# 2010| r2010_15(TernaryPodObj) = Load[x] : &:r2010_14, ~m?
|
||||
# 2010| r2010_16(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| mu2010_17(TernaryPodObj) = Store[#temp2010:10] : &:r2010_16, r2010_15
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2010| Block 12
|
||||
# 2010| r2010_12(glval<TernaryPodObj>) = VariableAddress[#temp2010:21] :
|
||||
# 2010| r2010_13(TernaryPodObj) = Constant[0] :
|
||||
# 2010| mu2010_14(TernaryPodObj) = Store[#temp2010:21] : &:r2010_12, r2010_13
|
||||
# 2010| r2010_15(TernaryPodObj) = Load[#temp2010:21] : &:r2010_12, ~m?
|
||||
# 2010| r2010_16(glval<TernaryPodObj>) = VariableAddress[y] :
|
||||
# 2010| mu2010_17(TernaryPodObj) = Store[y] : &:r2010_16, r2010_15
|
||||
# 2010| r2010_18(TernaryPodObj) = CopyValue : r2010_15
|
||||
# 2010| r2010_19(glval<TernaryPodObj>) = VariableAddress[#temp2010:9] :
|
||||
# 2010| mu2010_20(TernaryPodObj) = Store[#temp2010:9] : &:r2010_19, r2010_18
|
||||
# 2010| r2010_18(glval<TernaryPodObj>) = VariableAddress[y] :
|
||||
# 2010| r2010_19(TernaryPodObj) = Load[y] : &:r2010_18, ~m?
|
||||
# 2010| r2010_20(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| mu2010_21(TernaryPodObj) = Store[#temp2010:10] : &:r2010_20, r2010_19
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2013| TernaryNonPodObj& TernaryNonPodObj::operator=(TernaryNonPodObj const&)
|
||||
@@ -10931,46 +10931,46 @@ ir.cpp:
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2021| Block 10
|
||||
# 2021| r2021_6(glval<unknown>) = VariableAddress[#temp2021:9] :
|
||||
# 2021| r2021_7(glval<TernaryNonPodObj>) = Load[#temp2021:9] : &:r2021_6, ~m?
|
||||
# 2021| r2021_8(glval<TernaryNonPodObj>) = Convert : r2021_7
|
||||
# 2021| r2021_9(TernaryNonPodObj &) = CopyValue : r2021_8
|
||||
# 2021| r2021_10(TernaryNonPodObj &) = Call[operator=] : func:r2021_2, this:r2021_1, 0:r2021_9
|
||||
# 2021| mu2021_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_12(void) = ^IndirectReadSideEffect[-1] : &:r2021_1, ~m?
|
||||
# 2021| v2021_13(void) = ^BufferReadSideEffect[0] : &:r2021_9, ~m?
|
||||
# 2021| mu2021_14(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_1
|
||||
# 2021| r2021_15(glval<TernaryNonPodObj>) = CopyValue : r2021_10
|
||||
# 2022| v2022_1(void) = NoOp :
|
||||
# 2017| v2017_12(void) = ReturnVoid :
|
||||
# 2017| v2017_13(void) = AliasedUse : ~m?
|
||||
# 2017| v2017_14(void) = ExitFunction :
|
||||
# 2021| r2021_6(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| r2021_7(glval<TernaryNonPodObj>) = Load[#temp2021:10] : &:r2021_6, ~m?
|
||||
# 2021| r2021_8(glval<TernaryNonPodObj>) = Convert : r2021_7
|
||||
# 2021| r2021_9(TernaryNonPodObj &) = CopyValue : r2021_8
|
||||
# 2021| r2021_10(TernaryNonPodObj &) = Call[operator=] : func:r2021_2, this:r2021_1, 0:r2021_9
|
||||
# 2021| mu2021_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_12(void) = ^IndirectReadSideEffect[-1] : &:r2021_1, ~m?
|
||||
# 2021| v2021_13(void) = ^BufferReadSideEffect[0] : &:r2021_9, ~m?
|
||||
# 2021| mu2021_14(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_1
|
||||
# 2021| r2021_15(glval<TernaryNonPodObj>) = CopyValue : r2021_10
|
||||
# 2021| r2021_16(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2021| r2021_17(glval<TernaryNonPodObj>) = VariableAddress[#temp2021:23] :
|
||||
# 2021| mu2021_18(TernaryNonPodObj) = Uninitialized[#temp2021:23] : &:r2021_17
|
||||
# 2021| r2021_19(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2021| v2021_20(void) = Call[TernaryNonPodObj] : func:r2021_19, this:r2021_17
|
||||
# 2021| mu2021_21(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| mu2021_22(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_17
|
||||
# 2021| r2021_23(glval<TernaryNonPodObj>) = Convert : r2021_17
|
||||
# 2021| r2021_24(TernaryNonPodObj &) = CopyValue : r2021_23
|
||||
# 2021| r2021_25(TernaryNonPodObj &) = Call[operator=] : func:r2021_16, this:r2021_15, 0:r2021_24
|
||||
# 2021| mu2021_26(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_27(void) = ^IndirectReadSideEffect[-1] : &:r2021_15, ~m?
|
||||
# 2021| v2021_28(void) = ^BufferReadSideEffect[0] : &:r2021_24, ~m?
|
||||
# 2021| mu2021_29(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_15
|
||||
# 2021| r2021_30(glval<TernaryNonPodObj>) = CopyValue : r2021_25
|
||||
# 2022| v2022_1(void) = NoOp :
|
||||
# 2017| v2017_12(void) = ReturnVoid :
|
||||
# 2017| v2017_13(void) = AliasedUse : ~m?
|
||||
# 2017| v2017_14(void) = ExitFunction :
|
||||
|
||||
# 2021| Block 11
|
||||
# 2021| r2021_16(glval<TernaryNonPodObj>) = VariableAddress[x] :
|
||||
# 2021| r2021_17(glval<unknown>) = VariableAddress[#temp2021:9] :
|
||||
# 2021| mu2021_18(glval<TernaryNonPodObj>) = Store[#temp2021:9] : &:r2021_17, r2021_16
|
||||
# 2021| r2021_31(glval<TernaryNonPodObj>) = VariableAddress[x] :
|
||||
# 2021| r2021_32(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| mu2021_33(glval<TernaryNonPodObj>) = Store[#temp2021:10] : &:r2021_32, r2021_31
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2021| Block 12
|
||||
# 2021| r2021_19(glval<TernaryNonPodObj>) = VariableAddress[y] :
|
||||
# 2021| r2021_20(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2021| r2021_21(glval<TernaryNonPodObj>) = VariableAddress[#temp2021:21] :
|
||||
# 2021| mu2021_22(TernaryNonPodObj) = Uninitialized[#temp2021:21] : &:r2021_21
|
||||
# 2021| r2021_23(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2021| v2021_24(void) = Call[TernaryNonPodObj] : func:r2021_23, this:r2021_21
|
||||
# 2021| mu2021_25(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| mu2021_26(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_21
|
||||
# 2021| r2021_27(glval<TernaryNonPodObj>) = Convert : r2021_21
|
||||
# 2021| r2021_28(TernaryNonPodObj &) = CopyValue : r2021_27
|
||||
# 2021| r2021_29(TernaryNonPodObj &) = Call[operator=] : func:r2021_20, this:r2021_19, 0:r2021_28
|
||||
# 2021| mu2021_30(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_31(void) = ^IndirectReadSideEffect[-1] : &:r2021_19, ~m?
|
||||
# 2021| v2021_32(void) = ^BufferReadSideEffect[0] : &:r2021_28, ~m?
|
||||
# 2021| mu2021_33(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_19
|
||||
# 2021| r2021_34(glval<TernaryNonPodObj>) = CopyValue : r2021_29
|
||||
# 2021| r2021_35(glval<unknown>) = VariableAddress[#temp2021:9] :
|
||||
# 2021| mu2021_36(glval<TernaryNonPodObj>) = Store[#temp2021:9] : &:r2021_35, r2021_34
|
||||
# 2021| r2021_34(glval<TernaryNonPodObj>) = VariableAddress[y] :
|
||||
# 2021| r2021_35(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| mu2021_36(glval<TernaryNonPodObj>) = Store[#temp2021:10] : &:r2021_35, r2021_34
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
perf-regression.cpp:
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added more dataflow steps for `java.io.InputStream`s that wrap other `java.io.InputStream`s.
|
||||
@@ -4849,15 +4849,6 @@ extensions:
|
||||
- ["org.apache.struts2", "StrutsException", true, "StrutsException", "(Throwable,Object)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.apache.struts2", "StrutsException", true, "StrutsException", "(Throwable,Object)", "", "Argument[1]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.apache.struts2", "StrutsException", true, "toString", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "Order", "(String,String,int)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "Order", "(String,String,int)", "", "Argument[1]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "getClientName", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "getId", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "setClientName", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "setId", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", true, "toString", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", true, "create", "()", "", "Argument[this]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", true, "setId", "(String)", "", "Argument[0]", "Argument[this]", "taint", "df-generated"]
|
||||
- addsTo:
|
||||
pack: codeql/java-all
|
||||
extensible: neutralModel
|
||||
@@ -6886,19 +6877,5 @@ extensions:
|
||||
- ["org.apache.struts2", "ServletActionContext", "setResponse", "(HttpServletResponse)", "summary", "df-generated"]
|
||||
- ["org.apache.struts2", "ServletActionContext", "setServletContext", "(ServletContext)", "summary", "df-generated"]
|
||||
- ["org.apache.struts2", "ServletCache", "clear", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "IndexController", "index", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", "getAmount", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "Order", "setAmount", "(int)", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "deleteConfirm", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "destroy", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "edit", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "editNew", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "index", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "show", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersController", "update", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersService", "get", "(String)", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersService", "getAll", "()", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersService", "remove", "(String)", "summary", "df-generated"]
|
||||
- ["org.demo.rest.example", "OrdersService", "save", "(Order)", "summary", "df-generated"]
|
||||
- ["org.w3c.dom", "Document", "getElementsByTagName", "(String)", "summary", "df-generated"]
|
||||
- ["org.w3c.dom", "Document", "getElementsByTagNameNS", "(String,String)", "summary", "df-generated"]
|
||||
|
||||
@@ -177,6 +177,11 @@ class TypeObjectInputStream extends RefType {
|
||||
TypeObjectInputStream() { this.hasQualifiedName("java.io", "ObjectInputStream") }
|
||||
}
|
||||
|
||||
/** The class `java.io.InputStream`. */
|
||||
class TypeInputStream extends RefType {
|
||||
TypeInputStream() { this.hasQualifiedName("java.io", "InputStream") }
|
||||
}
|
||||
|
||||
/** The class `java.nio.file.Paths`. */
|
||||
class TypePaths extends Class {
|
||||
TypePaths() { this.hasQualifiedName("java.nio.file", "Paths") }
|
||||
|
||||
@@ -20,11 +20,11 @@ private module Frameworks {
|
||||
private import semmle.code.java.frameworks.Guice
|
||||
private import semmle.code.java.frameworks.IoJsonWebToken
|
||||
private import semmle.code.java.frameworks.jackson.JacksonSerializability
|
||||
private import semmle.code.java.frameworks.InputStream
|
||||
private import semmle.code.java.frameworks.Properties
|
||||
private import semmle.code.java.frameworks.Protobuf
|
||||
private import semmle.code.java.frameworks.ratpack.RatpackExec
|
||||
private import semmle.code.java.frameworks.stapler.Stapler
|
||||
private import semmle.code.java.JDK
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -757,7 +757,7 @@ private predicate baseBound(Expr e, int b, boolean upper) {
|
||||
or
|
||||
exists(Method read |
|
||||
e.(MethodAccess).getMethod().overrides*(read) and
|
||||
read.getDeclaringType().hasQualifiedName("java.io", "InputStream") and
|
||||
read.getDeclaringType() instanceof TypeInputStream and
|
||||
read.hasName("read") and
|
||||
read.getNumberOfParameters() = 0
|
||||
|
|
||||
|
||||
@@ -239,7 +239,7 @@ private class BulkData extends RefType {
|
||||
this.(Array).getElementType().(PrimitiveType).hasName(["byte", "char"])
|
||||
or
|
||||
exists(RefType t | this.getASourceSupertype*() = t |
|
||||
t.hasQualifiedName("java.io", "InputStream") or
|
||||
t instanceof TypeInputStream or
|
||||
t.hasQualifiedName("java.nio", "ByteBuffer") or
|
||||
t.hasQualifiedName("java.lang", "Readable") or
|
||||
t.hasQualifiedName("java.io", "DataInput") or
|
||||
@@ -259,7 +259,7 @@ private class BulkData extends RefType {
|
||||
private predicate inputStreamWrapper(Constructor c, int argi) {
|
||||
not c.fromSource() and
|
||||
c.getParameterType(argi) instanceof BulkData and
|
||||
c.getDeclaringType().getASourceSupertype+().hasQualifiedName("java.io", "InputStream")
|
||||
c.getDeclaringType().getASourceSupertype+() instanceof TypeInputStream
|
||||
}
|
||||
|
||||
/** An object construction that preserves the data flow status of any of its arguments. */
|
||||
|
||||
@@ -102,7 +102,7 @@ private module Dispatch {
|
||||
or
|
||||
t instanceof Interface and not t.fromSource()
|
||||
or
|
||||
t.hasQualifiedName("java.io", "InputStream")
|
||||
t instanceof TypeInputStream
|
||||
or
|
||||
t.hasQualifiedName("java.io", "Serializable")
|
||||
or
|
||||
|
||||
90
java/ql/lib/semmle/code/java/frameworks/InputStream.qll
Normal file
90
java/ql/lib/semmle/code/java/frameworks/InputStream.qll
Normal file
@@ -0,0 +1,90 @@
|
||||
/** Provides definitions related to `java.io.InputStream`. */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
private import semmle.code.java.dataflow.SSA
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* A jump taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method
|
||||
* to a class instance expression of the type extending `InputStream`.
|
||||
*
|
||||
* This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will
|
||||
* normally only happen in nested classes.
|
||||
*/
|
||||
private class InputStreamWrapperCapturedJumpStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(InputStreamRead m, NestedClass wrapper |
|
||||
m.getDeclaringType() = wrapper and
|
||||
wrapper.getASourceSupertype+() instanceof TypeInputStream
|
||||
|
|
||||
n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and
|
||||
n2.asExpr()
|
||||
.(ClassInstanceExpr)
|
||||
.getConstructedType()
|
||||
.getASourceSupertype*()
|
||||
.getSourceDeclaration() = wrapper
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A local taint step from the definition of a captured variable, the capturer of which
|
||||
* updates the `bytes[]` parameter in an override of the `InputStream.read` method,
|
||||
* to a class instance expression of the type extending `InputStream`.
|
||||
*
|
||||
* This models how a subtype of `InputStream` could be tainted by capturing tainted variables in
|
||||
* the definition of its methods.
|
||||
*/
|
||||
private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(InputStreamRead m, NestedClass wrapper, SsaVariable captured, SsaImplicitInit capturer |
|
||||
wrapper.getASourceSupertype+() instanceof TypeInputStream and
|
||||
m.getDeclaringType() = wrapper and
|
||||
capturer.captures(captured) and
|
||||
TaintTracking::localTaint(DataFlow::exprNode(capturer.getAFirstUse()),
|
||||
any(DataFlow::PostUpdateNode pun |
|
||||
pun.getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess()
|
||||
)) and
|
||||
n2.asExpr()
|
||||
.(ClassInstanceExpr)
|
||||
.getConstructedType()
|
||||
.getASourceSupertype*()
|
||||
.getSourceDeclaration() = wrapper
|
||||
|
|
||||
n1.asExpr() = captured.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource()
|
||||
or
|
||||
captured.(SsaImplicitInit).isParameterDefinition(n1.asParameter())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype
|
||||
* to the call of the constructor, only if the argument is assigned to a class field.
|
||||
*
|
||||
* This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream,
|
||||
* and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations.
|
||||
*/
|
||||
private class InputStreamWrapperConstructorStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(ClassInstanceExpr cc, Argument a, AssignExpr ae, int pos |
|
||||
cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and
|
||||
cc.getArgument(pragma[only_bind_into](pos)) = a and
|
||||
cc.getCallee().getParameter(pragma[only_bind_into](pos)).getAnAccess() = ae.getRhs() and
|
||||
ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof
|
||||
TypeInputStream
|
||||
|
|
||||
n1.asExpr() = a and
|
||||
n2.asExpr() = cc
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class InputStreamRead extends Method {
|
||||
InputStreamRead() {
|
||||
this.hasName("read") and
|
||||
this.getDeclaringType().getASourceSupertype*() instanceof TypeInputStream
|
||||
}
|
||||
}
|
||||
@@ -317,7 +317,7 @@ class SystemSetInputStreamMethod extends Method {
|
||||
SystemSetInputStreamMethod() {
|
||||
this.hasName("setIn") and
|
||||
this.getNumberOfParameters() = 1 and
|
||||
this.getParameter(0).getType().(RefType).hasQualifiedName("java.io", "InputStream") and
|
||||
this.getParameter(0).getType() instanceof TypeInputStream and
|
||||
this.getDeclaringType()
|
||||
.getAnAncestor()
|
||||
.getSourceDeclaration()
|
||||
|
||||
@@ -237,7 +237,7 @@ class SpringRequestMappingParameter extends Parameter {
|
||||
|
||||
private predicate isExplicitlyTaintedInput() {
|
||||
// InputStream or Reader parameters allow access to the body of a request
|
||||
this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "InputStream") or
|
||||
this.getType().(RefType).getAnAncestor() instanceof TypeInputStream or
|
||||
this.getType().(RefType).getAnAncestor().hasQualifiedName("java.io", "Reader") or
|
||||
// The SpringServletInputAnnotations allow access to the URI, request parameters, cookie values and the body of the request
|
||||
this.getAnAnnotation() instanceof SpringServletInputAnnotation or
|
||||
|
||||
139
java/ql/test/library-tests/dataflow/stream-read/A.java
Normal file
139
java/ql/test/library-tests/dataflow/stream-read/A.java
Normal file
@@ -0,0 +1,139 @@
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class A {
|
||||
|
||||
private static InputStream source() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void sink(Object s) {}
|
||||
|
||||
static class MyStream extends InputStream {
|
||||
private InputStream wrapped;
|
||||
|
||||
MyStream(InputStream wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return wrapped.read(b);
|
||||
}
|
||||
}
|
||||
|
||||
public static void testSeveralWrappers() {
|
||||
InputStream src = source();
|
||||
InputStream wrapper1 = new MyStream(src);
|
||||
sink(wrapper1); // $ hasTaintFlow
|
||||
InputStream wrapper2 = new MyStream(wrapper1);
|
||||
sink(wrapper2); // $ hasTaintFlow
|
||||
InputStream wrapper3 = new MyStream(wrapper2);
|
||||
sink(wrapper3); // $ hasTaintFlow
|
||||
|
||||
InputStream wrapper4 = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return wrapper3.read(b);
|
||||
|
||||
}
|
||||
};
|
||||
sink(wrapper4); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static void testAnonymous() throws Exception {
|
||||
InputStream wrapper = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
InputStream in = source();
|
||||
return in.read(b);
|
||||
}
|
||||
};
|
||||
sink(wrapper); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static void testAnonymousVarCapture() throws Exception {
|
||||
InputStream in = source();
|
||||
InputStream wrapper = new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return in.read(b);
|
||||
|
||||
}
|
||||
};
|
||||
sink(wrapper); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static InputStream wrapStream(InputStream in) {
|
||||
return new InputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return in.read(b);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void testWrapCall() {
|
||||
sink(wrapStream(null)); // $ SPURIOUS: hasTaintFlow
|
||||
sink(wrapStream(source())); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static void testLocal() {
|
||||
|
||||
class LocalInputStream extends InputStream {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
InputStream in = source();
|
||||
return in.read(b);
|
||||
}
|
||||
}
|
||||
sink(new LocalInputStream()); // $ hasTaintFlow
|
||||
}
|
||||
|
||||
public static void testLocalVarCapture() {
|
||||
InputStream in = source();
|
||||
|
||||
class LocalInputStream extends InputStream {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return in.read(b);
|
||||
}
|
||||
}
|
||||
sink(new LocalInputStream()); // $ hasTaintFlow
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
failures
|
||||
testFailures
|
||||
2
java/ql/test/library-tests/dataflow/stream-read/test.ql
Normal file
2
java/ql/test/library-tests/dataflow/stream-read/test.ql
Normal file
@@ -0,0 +1,2 @@
|
||||
import TestUtilities.InlineFlowTest
|
||||
import DefaultFlowTest
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
|
||||
* Added taint flow for `NSUserActivity.referrerURL`.
|
||||
@@ -83,7 +83,7 @@ private class UserActivityUrlInheritTaint extends TaintInheritingContent,
|
||||
{
|
||||
UserActivityUrlInheritTaint() {
|
||||
this.getField().getEnclosingDecl().asNominalTypeDecl().getName() = "NSUserActivity" and
|
||||
this.getField().getName() = "webpageURL"
|
||||
this.getField().getName() = ["webpageURL", "referrerURL"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about system
|
||||
* commands built from user-controlled sources (that is, command injection
|
||||
* vulnerabilities).
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* A dataflow sink for command injection vulnerabilities.
|
||||
*/
|
||||
abstract class CommandInjectionSink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A barrier for command injection vulnerabilities.
|
||||
*/
|
||||
abstract class CommandInjectionBarrier extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A unit class for adding additional flow steps.
|
||||
*/
|
||||
class CommandInjectionAdditionalFlowStep extends Unit {
|
||||
/**
|
||||
* Holds if the step from `node1` to `node2` should be considered a flow
|
||||
* step for paths related to command injection vulnerabilities.
|
||||
*/
|
||||
abstract predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo);
|
||||
}
|
||||
|
||||
private class ProcessSink2 extends CommandInjectionSink instanceof DataFlow::Node {
|
||||
ProcessSink2() {
|
||||
exists(AssignExpr assign, ProcessHost s |
|
||||
assign.getDest() = s and
|
||||
this.asExpr() = assign.getSource()
|
||||
)
|
||||
or
|
||||
exists(AssignExpr assign, ProcessHost s, ArrayExpr a |
|
||||
assign.getDest() = s and
|
||||
a = assign.getSource() and
|
||||
this.asExpr() = a.getAnElement()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class ProcessHost extends MemberRefExpr {
|
||||
ProcessHost() { this.getBase() instanceof ProcessRef }
|
||||
}
|
||||
|
||||
/** An expression of type `Process`. */
|
||||
private class ProcessRef extends Expr {
|
||||
ProcessRef() {
|
||||
this.getType() instanceof ProcessType or
|
||||
this.getType() = any(OptionalType t | t.getBaseType() instanceof ProcessType)
|
||||
}
|
||||
}
|
||||
|
||||
/** The type `Process`. */
|
||||
private class ProcessType extends NominalType {
|
||||
ProcessType() { this.getFullName() = "Process" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `DataFlow::Node` that is written into a `Process` object.
|
||||
*/
|
||||
private class ProcessSink extends CommandInjectionSink instanceof DataFlow::Node {
|
||||
ProcessSink() {
|
||||
// any write into a class derived from `Process` is a sink. For
|
||||
// example in `Process.launchPath = sensitive` the post-update node corresponding
|
||||
// with `Process.launchPath` is a sink.
|
||||
exists(NominalType t, Expr e |
|
||||
t.getABaseType*().getUnderlyingType().getName() = "Process" and
|
||||
e.getFullyConverted() = this.asExpr() and
|
||||
e.getFullyConverted().getType() = t
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink defined in a CSV model.
|
||||
*/
|
||||
private class DefaultCommandInjectionSink extends CommandInjectionSink {
|
||||
DefaultCommandInjectionSink() { sinkNode(this, "command-injection") }
|
||||
}
|
||||
31
swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll
Normal file
31
swift/ql/lib/codeql/swift/security/CommandInjectionQuery.qll
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Provides a taint-tracking configuration for reasoning about system
|
||||
* commands built from user-controlled sources (that is, Command injection
|
||||
* vulnerabilities).
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.FlowSources
|
||||
import codeql.swift.security.CommandInjectionExtensions
|
||||
|
||||
/**
|
||||
* A taint configuration for tainted data that reaches a Command Injection sink.
|
||||
*/
|
||||
module CommandInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node node) { node instanceof CommandInjectionSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof CommandInjectionBarrier }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
any(CommandInjectionAdditionalFlowStep s).step(nodeFrom, nodeTo)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect taint flow of tainted data that reaches a Command Injection sink.
|
||||
*/
|
||||
module CommandInjectionFlow = TaintTracking::Global<CommandInjectionConfig>;
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added new query "Command injection" (`swift/command-line-injection`). The query finds places where user input is used to execute system commands without proper escaping.
|
||||
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Constructing a system command with unsanitized user input is dangerous,
|
||||
since a malicious user may be able to craft input that executes arbitrary code.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
If possible, use hard-coded string literals to specify the command to run. Instead of interpreting
|
||||
user input directly as command names, examine the input and then choose among hard-coded string
|
||||
literals.
|
||||
</p>
|
||||
<p>
|
||||
If this is not possible, then add sanitization code to verify that the user input is safe before
|
||||
using it.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following examples execute code from user input without
|
||||
sanitizing it first:
|
||||
</p>
|
||||
<sample src="CommandInjectionBad.swift" />
|
||||
<p>
|
||||
If user input is used to construct a command it should be checked
|
||||
first. This ensures that the user cannot insert characters that have special
|
||||
meanings.
|
||||
</p>
|
||||
<sample src="CommandInjectionGood.swift" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name System command built from user-controlled sources
|
||||
* @description Building a system command from user-controlled sources is vulnerable to insertion of malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id swift/command-line-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-078
|
||||
* external/cwe/cwe-088
|
||||
*/
|
||||
|
||||
import swift
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
import codeql.swift.security.CommandInjectionQuery
|
||||
import CommandInjectionFlow::PathGraph
|
||||
|
||||
from CommandInjectionFlow::PathNode sourceNode, CommandInjectionFlow::PathNode sinkNode
|
||||
where CommandInjectionFlow::flowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode, "This command depends on a $@.",
|
||||
sourceNode.getNode(), "user-provided value"
|
||||
@@ -0,0 +1,5 @@
|
||||
var task = Process()
|
||||
task.launchPath = "/bin/bash"
|
||||
task.arguments = ["-c", userControlledString] // BAD
|
||||
|
||||
task.launch()
|
||||
@@ -0,0 +1,13 @@
|
||||
func validateCommand(_ command: String) -> String? {
|
||||
let allowedCommands = ["ls -l", "pwd", "echo"]
|
||||
if allowedCommands.contains(command) {
|
||||
return command
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var task = Process()
|
||||
task.launchPath = "/bin/bash"
|
||||
task.arguments = ["-c", validateCommand(userControlledString)] // GOOD
|
||||
|
||||
task.launch()
|
||||
@@ -0,0 +1,3 @@
|
||||
deadEnd
|
||||
| customurlschemes.swift:94:59:94:76 | options |
|
||||
| customurlschemes.swift:133:59:133:76 | options |
|
||||
@@ -1,6 +1,21 @@
|
||||
import swift
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import FlowConfig
|
||||
import codeql.swift.dataflow.TaintTracking
|
||||
import codeql.swift.dataflow.DataFlow
|
||||
|
||||
module TestConfiguration implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { src instanceof FlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(CallExpr sinkCall |
|
||||
sinkCall.getStaticTarget().getName().matches("sink%") and
|
||||
sinkCall.getAnArgument().getExpr() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module TestFlow = TaintTracking::Global<TestConfiguration>;
|
||||
|
||||
string describe(FlowSource source) {
|
||||
source instanceof RemoteFlowSource and result = "remote"
|
||||
@@ -9,7 +24,7 @@ string describe(FlowSource source) {
|
||||
}
|
||||
|
||||
module FlowSourcesTest implements TestSig {
|
||||
string getARelevantTag() { result = "source" }
|
||||
string getARelevantTag() { result = ["source", "tainted"] }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(FlowSource source |
|
||||
@@ -19,6 +34,16 @@ module FlowSourcesTest implements TestSig {
|
||||
tag = "source" and
|
||||
value = describe(source)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node sink |
|
||||
// this is not really what the "flowsources" test is about, but sometimes it's helpful to
|
||||
// have sinks and confirm that taint reaches obvious points in the flow source test code.
|
||||
TestFlow::flowTo(sink) and
|
||||
location = sink.getLocation() and
|
||||
element = sink.toString() and
|
||||
tag = "tainted" and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,24 @@ protocol UIApplicationDelegate {
|
||||
}
|
||||
|
||||
class UIScene {
|
||||
class ConnectionOptions {}
|
||||
class ConnectionOptions {
|
||||
var userActivities: Set<NSUserActivity> { get { return Set() } }
|
||||
var urlContexts: Set<UIOpenURLContext> { get { return Set() } }
|
||||
}
|
||||
}
|
||||
|
||||
class UISceneSession {}
|
||||
|
||||
class NSUserActivity {}
|
||||
class NSUserActivity: Hashable {
|
||||
static func == (lhs: NSUserActivity, rhs: NSUserActivity) -> Bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {}
|
||||
|
||||
var webpageURL: URL? { get { return nil } set { } }
|
||||
var referrerURL: URL? { get { return nil } set { } }
|
||||
}
|
||||
|
||||
class UIOpenURLContext: Hashable {
|
||||
static func == (lhs: UIOpenURLContext, rhs: UIOpenURLContext) -> Bool {
|
||||
@@ -39,6 +51,8 @@ class UIOpenURLContext: Hashable {
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {}
|
||||
|
||||
var url: URL { get { return URL() } }
|
||||
}
|
||||
|
||||
protocol UISceneDelegate {
|
||||
@@ -48,6 +62,8 @@ protocol UISceneDelegate {
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>)
|
||||
}
|
||||
|
||||
func sink(arg: Any) {}
|
||||
|
||||
// --- tests ---
|
||||
|
||||
class AppDelegate: UIApplicationDelegate {
|
||||
@@ -64,28 +80,88 @@ class AppDelegate: UIApplicationDelegate {
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
|
||||
launchOptions?[.url] // $ source=remote
|
||||
_ = launchOptions?[.url] // $ source=remote
|
||||
return true
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
|
||||
launchOptions?[.url] // $ source=remote
|
||||
_ = launchOptions?[.url] // $ source=remote
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class SceneDelegate : UISceneDelegate {
|
||||
func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // $ source=remote
|
||||
func scene(_: UIScene, continue: NSUserActivity) {} // $ source=remote
|
||||
func scene(_: UIScene, didUpdate: NSUserActivity) {} // $ source=remote
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>) {} // $ source=remote
|
||||
func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) { // $ source=remote
|
||||
for userActivity in options.userActivities {
|
||||
let x = userActivity.webpageURL
|
||||
sink(arg: x) // $ MISSING: tainted
|
||||
let y = userActivity.referrerURL
|
||||
sink(arg: y) // $ MISSING: tainted
|
||||
}
|
||||
|
||||
for urlContext in options.urlContexts {
|
||||
let z = urlContext.url
|
||||
sink(arg: z) // $ MISSING: tainted
|
||||
}
|
||||
}
|
||||
|
||||
func scene(_: UIScene, continue: NSUserActivity) { // $ source=remote
|
||||
let x = `continue`.webpageURL
|
||||
sink(arg: x) // $ tainted
|
||||
let y = `continue`.referrerURL
|
||||
sink(arg: y) // $ tainted
|
||||
}
|
||||
|
||||
func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote
|
||||
let x = didUpdate.webpageURL
|
||||
sink(arg: x) // $ tainted
|
||||
let y = didUpdate.referrerURL
|
||||
sink(arg: y) // $ tainted
|
||||
}
|
||||
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>) { // $ source=remote
|
||||
for openURLContext in openURLContexts {
|
||||
let x = openURLContext.url
|
||||
sink(arg: x) // $ MISSING: tainted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Extended {}
|
||||
|
||||
extension Extended : UISceneDelegate {
|
||||
func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) {} // $ source=remote
|
||||
func scene(_: UIScene, continue: NSUserActivity) {} // $ source=remote
|
||||
func scene(_: UIScene, didUpdate: NSUserActivity) {} // $ source=remote
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>) {} // $ source=remote
|
||||
func scene(_: UIScene, willConnectTo: UISceneSession, options: UIScene.ConnectionOptions) { // $ source=remote
|
||||
for userActivity in options.userActivities {
|
||||
let x = userActivity.webpageURL
|
||||
sink(arg: x) // $ MISSING: tainted
|
||||
let y = userActivity.referrerURL
|
||||
sink(arg: y) // $ MISSING: tainted
|
||||
}
|
||||
|
||||
for urlContext in options.urlContexts {
|
||||
let z = urlContext.url
|
||||
sink(arg: z) // $ MISSING: tainted
|
||||
}
|
||||
}
|
||||
|
||||
func scene(_: UIScene, continue: NSUserActivity) { // $ source=remote
|
||||
let x = `continue`.webpageURL
|
||||
sink(arg: x) // $ tainted
|
||||
let y = `continue`.referrerURL
|
||||
sink(arg: y) // $ tainted
|
||||
}
|
||||
|
||||
func scene(_: UIScene, didUpdate: NSUserActivity) { // $ source=remote
|
||||
let x = didUpdate.webpageURL
|
||||
sink(arg: x) // $ tainted
|
||||
let y = didUpdate.referrerURL
|
||||
sink(arg: y) // $ tainted
|
||||
}
|
||||
|
||||
func scene(_: UIScene, openURLContexts: Set<UIOpenURLContext>) { // $ source=remote
|
||||
for openURLContext in openURLContexts {
|
||||
let x = openURLContext.url
|
||||
sink(arg: x) // $ MISSING: tainted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user