Merge branch 'main' into add-using-expired-stack-address-query

This commit is contained in:
Mathias Vorreiter Pedersen
2022-02-24 08:41:27 +00:00
170 changed files with 13267 additions and 816 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Add relation for tracking variables from structured binding declarations
compatibility: full
is_structured_binding.rel: delete

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added a `isStructuredBinding` predicate to the `Variable` class which holds when the variable is declared as part of a structured binding declaration.

View File

@@ -169,6 +169,12 @@ class Variable extends Declaration, @variable {
variable_instantiation(underlyingElement(this), unresolveElement(v))
}
/**
* Holds if this variable is declated as part of a structured binding
* declaration. For example, `x` in `auto [x, y] = ...`.
*/
predicate isStructuredBinding() { is_structured_binding(underlyingElement(this)) }
/**
* Holds if this is a compiler-generated variable. For example, a
* [range-based for loop](http://en.cppreference.com/w/cpp/language/range-for)

View File

@@ -446,6 +446,7 @@ var_decl_specifiers(
int id: @var_decl ref,
string name: string ref
)
is_structured_binding(unique int id: @variable ref);
type_decls(
unique int id: @type_decl,

View File

@@ -14877,6 +14877,17 @@
</dependencies>
</relation>
<relation>
<name>is_structured_binding</name>
<cardinality>10</cardinality>
<columnsizes>
<e>
<k>id</k>
<v>10</v>
</e>
</columnsizes>
<dependencies/>
</relation>
<relation>
<name>type_decls</name>
<cardinality>1316547</cardinality>
<columnsizes>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add relation for tracking variables from structured binding declarations
compatibility: backwards

View File

@@ -18,7 +18,6 @@ where
not lv1.isCompilerGenerated() and
not lv2.isCompilerGenerated() and
not lv1.getParentScope().(BlockStmt).isInMacroExpansion() and
not lv2.getParentScope().(BlockStmt).isInMacroExpansion() and
not lv1.getName() = "(unnamed local variable)"
not lv2.getParentScope().(BlockStmt).isInMacroExpansion()
select lv1, "Variable " + lv1.getName() + " hides another variable of the same name (on $@).", lv2,
"line " + lv2.getLocation().getStartLine().toString()

View File

@@ -11390,6 +11390,872 @@ ir.cpp:
# 1458| Value = [Literal] 3
# 1458| ValueCategory = prvalue
# 1459| getStmt(1): [ReturnStmt] return ...
# 1462| [TopLevelFunction] void array_structured_binding()
# 1462| <params>:
# 1462| getEntryPoint(): [BlockStmt] { ... }
# 1463| getStmt(0): [DeclStmt] declaration
# 1463| getDeclarationEntry(0): [VariableDeclarationEntry] definition of xs
# 1463| Type = [ArrayType] int[2]
# 1463| getVariable().getInitializer(): [Initializer] initializer for xs
# 1463| getExpr(): [ArrayAggregateLiteral] {...}
# 1463| Type = [ArrayType] int[2]
# 1463| ValueCategory = prvalue
# 1463| getElementExpr(0): [Literal] 1
# 1463| Type = [IntType] int
# 1463| Value = [Literal] 1
# 1463| ValueCategory = prvalue
# 1463| getElementExpr(1): [Literal] 2
# 1463| Type = [IntType] int
# 1463| Value = [Literal] 2
# 1463| ValueCategory = prvalue
# 1465| getStmt(1): [BlockStmt] { ... }
# 1466| getStmt(0): [DeclStmt] declaration
# 1466| getDeclarationEntry(0): (no string representation)
# 1466| Type = [LValueReferenceType] int(&)[2]
# 1466| getVariable().getInitializer(): [Initializer] initializer for (unnamed local variable)
# 1466| getExpr(): [VariableAccess] xs
# 1466| Type = [ArrayType] int[2]
# 1466| ValueCategory = lvalue
# 1466| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1466| Type = [LValueReferenceType] int(&)[2]
# 1466| ValueCategory = prvalue
# 1466| getDeclarationEntry(1): [VariableDeclarationEntry] definition of x0
# 1466| Type = [IntType] int
#-----| getVariable().getInitializer(): [Initializer] initializer for x0
#-----| getExpr(): [ArrayExpr] access to array
#-----| Type = [IntType] int
#-----| ValueCategory = lvalue
#-----| getArrayBase(): [VariableAccess] (unnamed local variable)
#-----| Type = [LValueReferenceType] int(&)[2]
#-----| ValueCategory = prvalue(load)
#-----| getArrayOffset(): [Literal] 0
#-----| Type = [LongType] unsigned long
#-----| Value = [Literal] 0
#-----| ValueCategory = prvalue
#-----| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
#-----| Type = [IntPointerType] int *
#-----| ValueCategory = prvalue
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ArrayType] int[2]
#-----| ValueCategory = lvalue
# 1466| getDeclarationEntry(2): [VariableDeclarationEntry] definition of x1
# 1466| Type = [IntType] int
#-----| getVariable().getInitializer(): [Initializer] initializer for x1
#-----| getExpr(): [ArrayExpr] access to array
#-----| Type = [IntType] int
#-----| ValueCategory = lvalue
#-----| getArrayBase(): [VariableAccess] (unnamed local variable)
#-----| Type = [LValueReferenceType] int(&)[2]
#-----| ValueCategory = prvalue(load)
#-----| getArrayOffset(): [Literal] 1
#-----| Type = [LongType] unsigned long
#-----| Value = [Literal] 1
#-----| ValueCategory = prvalue
#-----| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
#-----| Type = [IntPointerType] int *
#-----| ValueCategory = prvalue
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ArrayType] int[2]
#-----| ValueCategory = lvalue
# 1467| getStmt(1): [ExprStmt] ExprStmt
# 1467| getExpr(): [AssignExpr] ... = ...
# 1467| Type = [IntType] int
# 1467| ValueCategory = lvalue
# 1467| getLValue(): [VariableAccess] x1
# 1467| Type = [IntType] int
# 1467| ValueCategory = lvalue
# 1467| getRValue(): [Literal] 3
# 1467| Type = [IntType] int
# 1467| Value = [Literal] 3
# 1467| ValueCategory = prvalue
# 1468| getStmt(2): [DeclStmt] declaration
# 1468| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rx1
# 1468| Type = [LValueReferenceType] int &
# 1468| getVariable().getInitializer(): [Initializer] initializer for rx1
# 1468| getExpr(): [VariableAccess] x1
# 1468| Type = [IntType] int
# 1468| ValueCategory = lvalue
# 1468| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1468| Type = [LValueReferenceType] int &
# 1468| ValueCategory = prvalue
# 1469| getStmt(3): [DeclStmt] declaration
# 1469| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 1469| Type = [IntType] int
# 1469| getVariable().getInitializer(): [Initializer] initializer for x
# 1469| getExpr(): [VariableAccess] x1
# 1469| Type = [IntType] int
# 1469| ValueCategory = prvalue(load)
# 1472| getStmt(2): [BlockStmt] { ... }
# 1473| getStmt(0): [DeclStmt] declaration
# 1473| getDeclarationEntry(0): [VariableDeclarationEntry] definition of unnamed_local_variable
# 1473| Type = [LValueReferenceType] int(&)[2]
# 1473| getVariable().getInitializer(): [Initializer] initializer for unnamed_local_variable
# 1473| getExpr(): [VariableAccess] xs
# 1473| Type = [ArrayType] int[2]
# 1473| ValueCategory = lvalue
# 1473| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1473| Type = [LValueReferenceType] int(&)[2]
# 1473| ValueCategory = prvalue
# 1474| getStmt(1): [DeclStmt] declaration
# 1474| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x0
# 1474| Type = [LValueReferenceType] int &
# 1474| getVariable().getInitializer(): [Initializer] initializer for x0
# 1474| getExpr(): [ArrayExpr] access to array
# 1474| Type = [IntType] int
# 1474| ValueCategory = lvalue
# 1474| getArrayBase(): [VariableAccess] xs
# 1474| Type = [ArrayType] int[2]
# 1474| ValueCategory = lvalue
# 1474| getArrayOffset(): [Literal] 0
# 1474| Type = [IntType] int
# 1474| Value = [Literal] 0
# 1474| ValueCategory = prvalue
# 1474| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 1474| Type = [IntPointerType] int *
# 1474| ValueCategory = prvalue
# 1474| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1474| Type = [LValueReferenceType] int &
# 1474| ValueCategory = prvalue
# 1475| getStmt(2): [DeclStmt] declaration
# 1475| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x1
# 1475| Type = [LValueReferenceType] int &
# 1475| getVariable().getInitializer(): [Initializer] initializer for x1
# 1475| getExpr(): [ArrayExpr] access to array
# 1475| Type = [IntType] int
# 1475| ValueCategory = lvalue
# 1475| getArrayBase(): [VariableAccess] xs
# 1475| Type = [ArrayType] int[2]
# 1475| ValueCategory = lvalue
# 1475| getArrayOffset(): [Literal] 1
# 1475| Type = [IntType] int
# 1475| Value = [Literal] 1
# 1475| ValueCategory = prvalue
# 1475| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 1475| Type = [IntPointerType] int *
# 1475| ValueCategory = prvalue
# 1475| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1475| Type = [LValueReferenceType] int &
# 1475| ValueCategory = prvalue
# 1476| getStmt(3): [ExprStmt] ExprStmt
# 1476| getExpr(): [AssignExpr] ... = ...
# 1476| Type = [IntType] int
# 1476| ValueCategory = lvalue
# 1476| getLValue(): [VariableAccess] x1
# 1476| Type = [LValueReferenceType] int &
# 1476| ValueCategory = prvalue(load)
# 1476| getRValue(): [Literal] 3
# 1476| Type = [IntType] int
# 1476| Value = [Literal] 3
# 1476| ValueCategory = prvalue
# 1476| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1476| Type = [IntType] int
# 1476| ValueCategory = lvalue
# 1477| getStmt(4): [DeclStmt] declaration
# 1477| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rx1
# 1477| Type = [LValueReferenceType] int &
# 1477| getVariable().getInitializer(): [Initializer] initializer for rx1
# 1477| getExpr(): [VariableAccess] x1
# 1477| Type = [LValueReferenceType] int &
# 1477| ValueCategory = prvalue(load)
# 1477| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1477| Type = [LValueReferenceType] int &
# 1477| ValueCategory = prvalue
# 1477| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1477| Type = [IntType] int
# 1477| ValueCategory = lvalue
# 1478| getStmt(5): [DeclStmt] declaration
# 1478| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 1478| Type = [IntType] int
# 1478| getVariable().getInitializer(): [Initializer] initializer for x
# 1478| getExpr(): [VariableAccess] x1
# 1478| Type = [LValueReferenceType] int &
# 1478| ValueCategory = prvalue(load)
# 1478| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1478| Type = [IntType] int
# 1478| ValueCategory = prvalue(load)
# 1480| getStmt(3): [ReturnStmt] return ...
# 1482| [CopyAssignmentOperator] StructuredBindingDataMemberStruct& StructuredBindingDataMemberStruct::operator=(StructuredBindingDataMemberStruct const&)
# 1482| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
# 1482| [Constructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct()
# 1482| <params>:
# 1482| <initializations>:
# 1482| getInitializer(0): [ConstructorFieldInit] constructor init of field i
# 1482| Type = [IntType] int
# 1482| ValueCategory = prvalue
# 1482| getInitializer(1): [ConstructorFieldInit] constructor init of field d
# 1482| Type = [DoubleType] double
# 1482| ValueCategory = prvalue
# 1482| getInitializer(2): [ConstructorFieldInit] constructor init of field r
# 1482| Type = [LValueReferenceType] int &
# 1482| ValueCategory = prvalue
# 1482| getEntryPoint(): [BlockStmt] { ... }
# 1482| getStmt(0): [ReturnStmt] return ...
# 1482| [CopyConstructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct const&)
# 1482| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
# 1482| <initializations>:
# 1482| getInitializer(0): [ConstructorFieldInit] constructor init of field i
# 1482| Type = [IntType] int
# 1482| ValueCategory = prvalue
# 1482| getExpr(): [Literal] Unknown literal
# 1482| Type = [IntType] int
# 1482| ValueCategory = prvalue
# 1482| getInitializer(1): [ConstructorFieldInit] constructor init of field d
# 1482| Type = [DoubleType] double
# 1482| ValueCategory = prvalue
# 1482| getExpr(): [Literal] Unknown literal
# 1482| Type = [DoubleType] double
# 1482| ValueCategory = prvalue
# 1482| getInitializer(2): [ConstructorFieldInit] constructor init of field b
# 1482| Type = [IntType] unsigned int
# 1482| ValueCategory = prvalue
# 1482| getExpr(): [Literal] Unknown literal
# 1482| Type = [IntType] unsigned int
# 1482| ValueCategory = prvalue
# 1482| getInitializer(3): [ConstructorFieldInit] constructor init of field r
# 1482| Type = [LValueReferenceType] int &
# 1482| ValueCategory = prvalue
# 1482| getExpr(): [Literal] Unknown literal
# 1482| Type = [LValueReferenceType] int &
# 1482| ValueCategory = prvalue
# 1482| getEntryPoint(): [BlockStmt] { ... }
# 1482| getStmt(0): [ReturnStmt] return ...
# 1482| [MoveConstructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct&&)
# 1482| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] StructuredBindingDataMemberStruct &&
# 1489| [TopLevelFunction] void data_member_structured_binding()
# 1489| <params>:
# 1489| getEntryPoint(): [BlockStmt] { ... }
# 1490| getStmt(0): [DeclStmt] declaration
# 1490| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
# 1490| Type = [Struct] StructuredBindingDataMemberStruct
# 1490| getVariable().getInitializer(): [Initializer] initializer for s
# 1490| getExpr(): [ConstructorCall] call to StructuredBindingDataMemberStruct
# 1490| Type = [VoidType] void
# 1490| ValueCategory = prvalue
# 1492| getStmt(1): [BlockStmt] { ... }
# 1493| getStmt(0): [DeclStmt] declaration
# 1493| getDeclarationEntry(0): (no string representation)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| getVariable().getInitializer(): [Initializer] initializer for (unnamed local variable)
# 1493| getExpr(): [VariableAccess] s
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = prvalue(load)
# 1493| getDeclarationEntry(1): [VariableDeclarationEntry] definition of i
# 1493| Type = [IntType] int
#-----| getVariable().getInitializer(): [Initializer] initializer for i
# 1493| getExpr(): [ValueFieldAccess] i
# 1493| Type = [IntType] int
# 1493| ValueCategory = lvalue
# 1493| getQualifier(): [VariableAccess] (unnamed local variable)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = lvalue
# 1493| getDeclarationEntry(2): [VariableDeclarationEntry] definition of d
# 1493| Type = [DoubleType] double
#-----| getVariable().getInitializer(): [Initializer] initializer for d
# 1493| getExpr(): [ValueFieldAccess] d
# 1493| Type = [DoubleType] double
# 1493| ValueCategory = lvalue
# 1493| getQualifier(): [VariableAccess] (unnamed local variable)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = lvalue
# 1493| getDeclarationEntry(3): [VariableDeclarationEntry] definition of b
# 1493| Type = [IntType] unsigned int
#-----| getVariable().getInitializer(): [Initializer] initializer for b
# 1493| getExpr(): [ValueFieldAccess] b
# 1493| Type = [IntType] unsigned int
# 1493| ValueCategory = lvalue
# 1493| getQualifier(): [VariableAccess] (unnamed local variable)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = lvalue
# 1493| getDeclarationEntry(4): [VariableDeclarationEntry] definition of r
# 1493| Type = [IntType] int
#-----| getVariable().getInitializer(): [Initializer] initializer for r
# 1493| getExpr(): [ValueFieldAccess] r
# 1493| Type = [LValueReferenceType] int &
# 1493| ValueCategory = prvalue(load)
# 1493| getQualifier(): [VariableAccess] (unnamed local variable)
# 1493| Type = [Struct] StructuredBindingDataMemberStruct
# 1493| ValueCategory = lvalue
# 1493| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1493| Type = [IntType] int
# 1493| ValueCategory = lvalue
# 1494| getStmt(1): [ExprStmt] ExprStmt
# 1494| getExpr(): [AssignExpr] ... = ...
# 1494| Type = [DoubleType] double
# 1494| ValueCategory = lvalue
# 1494| getLValue(): [VariableAccess] d
# 1494| Type = [DoubleType] double
# 1494| ValueCategory = lvalue
# 1494| getRValue(): [Literal] 4.0
# 1494| Type = [DoubleType] double
# 1494| Value = [Literal] 4.0
# 1494| ValueCategory = prvalue
# 1495| getStmt(2): [DeclStmt] declaration
# 1495| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rd
# 1495| Type = [LValueReferenceType] double &
# 1495| getVariable().getInitializer(): [Initializer] initializer for rd
# 1495| getExpr(): [VariableAccess] d
# 1495| Type = [DoubleType] double
# 1495| ValueCategory = lvalue
# 1495| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1495| Type = [LValueReferenceType] double &
# 1495| ValueCategory = prvalue
# 1496| getStmt(3): [DeclStmt] declaration
# 1496| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v
# 1496| Type = [IntType] int
# 1496| getVariable().getInitializer(): [Initializer] initializer for v
# 1496| getExpr(): [VariableAccess] i
# 1496| Type = [IntType] int
# 1496| ValueCategory = prvalue(load)
# 1497| getStmt(4): [ExprStmt] ExprStmt
# 1497| getExpr(): [AssignExpr] ... = ...
# 1497| Type = [IntType] int
# 1497| ValueCategory = lvalue
# 1497| getLValue(): [VariableAccess] r
# 1497| Type = [IntType] int
# 1497| ValueCategory = lvalue
# 1497| getRValue(): [Literal] 5
# 1497| Type = [IntType] int
# 1497| Value = [Literal] 5
# 1497| ValueCategory = prvalue
# 1498| getStmt(5): [DeclStmt] declaration
# 1498| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rr
# 1498| Type = [LValueReferenceType] int &
# 1498| getVariable().getInitializer(): [Initializer] initializer for rr
# 1498| getExpr(): [VariableAccess] r
# 1498| Type = [IntType] int
# 1498| ValueCategory = lvalue
# 1498| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1498| Type = [LValueReferenceType] int &
# 1498| ValueCategory = prvalue
# 1499| getStmt(6): [DeclStmt] declaration
# 1499| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 1499| Type = [IntType] int
# 1499| getVariable().getInitializer(): [Initializer] initializer for w
# 1499| getExpr(): [VariableAccess] r
# 1499| Type = [IntType] int
# 1499| ValueCategory = prvalue(load)
# 1502| getStmt(2): [BlockStmt] { ... }
# 1503| getStmt(0): [DeclStmt] declaration
# 1503| getDeclarationEntry(0): [VariableDeclarationEntry] definition of unnamed_local_variable
# 1503| Type = [Struct] StructuredBindingDataMemberStruct
# 1503| getVariable().getInitializer(): [Initializer] initializer for unnamed_local_variable
# 1503| getExpr(): [VariableAccess] s
# 1503| Type = [Struct] StructuredBindingDataMemberStruct
# 1503| ValueCategory = prvalue(load)
# 1504| getStmt(1): [DeclStmt] declaration
# 1504| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 1504| Type = [LValueReferenceType] int &
# 1504| getVariable().getInitializer(): [Initializer] initializer for i
# 1504| getExpr(): [ValueFieldAccess] i
# 1504| Type = [IntType] int
# 1504| ValueCategory = lvalue
# 1504| getQualifier(): [VariableAccess] unnamed_local_variable
# 1504| Type = [Struct] StructuredBindingDataMemberStruct
# 1504| ValueCategory = lvalue
# 1504| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1504| Type = [LValueReferenceType] int &
# 1504| ValueCategory = prvalue
# 1505| getStmt(2): [DeclStmt] declaration
# 1505| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
# 1505| Type = [LValueReferenceType] double &
# 1505| getVariable().getInitializer(): [Initializer] initializer for d
# 1505| getExpr(): [ValueFieldAccess] d
# 1505| Type = [DoubleType] double
# 1505| ValueCategory = lvalue
# 1505| getQualifier(): [VariableAccess] unnamed_local_variable
# 1505| Type = [Struct] StructuredBindingDataMemberStruct
# 1505| ValueCategory = lvalue
# 1505| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1505| Type = [LValueReferenceType] double &
# 1505| ValueCategory = prvalue
# 1507| getStmt(3): [DeclStmt] declaration
# 1507| getDeclarationEntry(0): [VariableDeclarationEntry] definition of r
# 1507| Type = [LValueReferenceType] int &
# 1507| getVariable().getInitializer(): [Initializer] initializer for r
# 1507| getExpr(): [ValueFieldAccess] r
# 1507| Type = [LValueReferenceType] int &
# 1507| ValueCategory = prvalue(load)
# 1507| getQualifier(): [VariableAccess] unnamed_local_variable
# 1507| Type = [Struct] StructuredBindingDataMemberStruct
# 1507| ValueCategory = lvalue
# 1507| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1507| Type = [LValueReferenceType] int &
# 1507| ValueCategory = prvalue
# 1507| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1507| Type = [IntType] int
# 1507| ValueCategory = lvalue
# 1508| getStmt(4): [ExprStmt] ExprStmt
# 1508| getExpr(): [AssignExpr] ... = ...
# 1508| Type = [DoubleType] double
# 1508| ValueCategory = lvalue
# 1508| getLValue(): [VariableAccess] d
# 1508| Type = [LValueReferenceType] double &
# 1508| ValueCategory = prvalue(load)
# 1508| getRValue(): [Literal] 4.0
# 1508| Type = [DoubleType] double
# 1508| Value = [Literal] 4.0
# 1508| ValueCategory = prvalue
# 1508| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1508| Type = [DoubleType] double
# 1508| ValueCategory = lvalue
# 1509| getStmt(5): [DeclStmt] declaration
# 1509| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rd
# 1509| Type = [LValueReferenceType] double &
# 1509| getVariable().getInitializer(): [Initializer] initializer for rd
# 1509| getExpr(): [VariableAccess] d
# 1509| Type = [LValueReferenceType] double &
# 1509| ValueCategory = prvalue(load)
# 1509| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1509| Type = [LValueReferenceType] double &
# 1509| ValueCategory = prvalue
# 1509| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1509| Type = [DoubleType] double
# 1509| ValueCategory = lvalue
# 1510| getStmt(6): [DeclStmt] declaration
# 1510| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v
# 1510| Type = [IntType] int
# 1510| getVariable().getInitializer(): [Initializer] initializer for v
# 1510| getExpr(): [VariableAccess] i
# 1510| Type = [LValueReferenceType] int &
# 1510| ValueCategory = prvalue(load)
# 1510| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1510| Type = [IntType] int
# 1510| ValueCategory = prvalue(load)
# 1511| getStmt(7): [ExprStmt] ExprStmt
# 1511| getExpr(): [AssignExpr] ... = ...
# 1511| Type = [IntType] int
# 1511| ValueCategory = lvalue
# 1511| getLValue(): [VariableAccess] r
# 1511| Type = [LValueReferenceType] int &
# 1511| ValueCategory = prvalue(load)
# 1511| getRValue(): [Literal] 5
# 1511| Type = [IntType] int
# 1511| Value = [Literal] 5
# 1511| ValueCategory = prvalue
# 1511| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1511| Type = [IntType] int
# 1511| ValueCategory = lvalue
# 1512| getStmt(8): [DeclStmt] declaration
# 1512| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rr
# 1512| Type = [LValueReferenceType] int &
# 1512| getVariable().getInitializer(): [Initializer] initializer for rr
# 1512| getExpr(): [VariableAccess] r
# 1512| Type = [LValueReferenceType] int &
# 1512| ValueCategory = prvalue(load)
# 1512| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1512| Type = [LValueReferenceType] int &
# 1512| ValueCategory = prvalue
# 1512| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1512| Type = [IntType] int
# 1512| ValueCategory = lvalue
# 1513| getStmt(9): [DeclStmt] declaration
# 1513| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 1513| Type = [IntType] int
# 1513| getVariable().getInitializer(): [Initializer] initializer for w
# 1513| getExpr(): [VariableAccess] r
# 1513| Type = [LValueReferenceType] int &
# 1513| ValueCategory = prvalue(load)
# 1513| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1513| Type = [IntType] int
# 1513| ValueCategory = prvalue(load)
# 1515| getStmt(3): [ReturnStmt] return ...
# 1522| [CopyAssignmentOperator] std::tuple_size<StructuredBindingTuple>& std::tuple_size<StructuredBindingTuple>::operator=(std::tuple_size<StructuredBindingTuple> const&)
# 1522| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const tuple_size<StructuredBindingTuple> &
# 1522| [MoveAssignmentOperator] std::tuple_size<StructuredBindingTuple>& std::tuple_size<StructuredBindingTuple>::operator=(std::tuple_size<StructuredBindingTuple>&&)
# 1522| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] tuple_size<StructuredBindingTuple> &&
# 1529| [CopyAssignmentOperator] std::tuple_element<int 0, StructuredBindingTuple>& std::tuple_element<int 0, StructuredBindingTuple>::operator=(std::tuple_element<int 0, StructuredBindingTuple> const&)
# 1529| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const tuple_element<0, StructuredBindingTuple> &
# 1529| [MoveAssignmentOperator] std::tuple_element<int 0, StructuredBindingTuple>& std::tuple_element<int 0, StructuredBindingTuple>::operator=(std::tuple_element<int 0, StructuredBindingTuple>&&)
# 1529| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] tuple_element<0, StructuredBindingTuple> &&
# 1533| [CopyAssignmentOperator] std::tuple_element<int 1, StructuredBindingTuple>& std::tuple_element<int 1, StructuredBindingTuple>::operator=(std::tuple_element<int 1, StructuredBindingTuple> const&)
# 1533| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const tuple_element<1, StructuredBindingTuple> &
# 1533| [MoveAssignmentOperator] std::tuple_element<int 1, StructuredBindingTuple>& std::tuple_element<int 1, StructuredBindingTuple>::operator=(std::tuple_element<int 1, StructuredBindingTuple>&&)
# 1533| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] tuple_element<1, StructuredBindingTuple> &&
# 1537| [CopyAssignmentOperator] std::tuple_element<int 2, StructuredBindingTuple>& std::tuple_element<int 2, StructuredBindingTuple>::operator=(std::tuple_element<int 2, StructuredBindingTuple> const&)
# 1537| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const tuple_element<2, StructuredBindingTuple> &
# 1537| [MoveAssignmentOperator] std::tuple_element<int 2, StructuredBindingTuple>& std::tuple_element<int 2, StructuredBindingTuple>::operator=(std::tuple_element<int 2, StructuredBindingTuple>&&)
# 1537| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] tuple_element<2, StructuredBindingTuple> &&
# 1542| [CopyAssignmentOperator] StructuredBindingTuple& StructuredBindingTuple::operator=(StructuredBindingTuple const&)
# 1542| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const StructuredBindingTuple &
# 1542| [Constructor] void StructuredBindingTuple::StructuredBindingTuple()
# 1542| <params>:
# 1542| <initializations>:
# 1542| getInitializer(0): [ConstructorFieldInit] constructor init of field i
# 1542| Type = [IntType] int
# 1542| ValueCategory = prvalue
# 1542| getInitializer(1): [ConstructorFieldInit] constructor init of field d
# 1542| Type = [DoubleType] double
# 1542| ValueCategory = prvalue
# 1542| getInitializer(2): [ConstructorFieldInit] constructor init of field r
# 1542| Type = [LValueReferenceType] int &
# 1542| ValueCategory = prvalue
# 1542| getEntryPoint(): [BlockStmt] { ... }
# 1542| getStmt(0): [ReturnStmt] return ...
# 1542| [CopyConstructor] void StructuredBindingTuple::StructuredBindingTuple(StructuredBindingTuple const&)
# 1542| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const StructuredBindingTuple &
# 1542| <initializations>:
# 1542| getInitializer(0): [ConstructorFieldInit] constructor init of field i
# 1542| Type = [IntType] int
# 1542| ValueCategory = prvalue
# 1542| getExpr(): [Literal] Unknown literal
# 1542| Type = [IntType] int
# 1542| ValueCategory = prvalue
# 1542| getInitializer(1): [ConstructorFieldInit] constructor init of field d
# 1542| Type = [DoubleType] double
# 1542| ValueCategory = prvalue
# 1542| getExpr(): [Literal] Unknown literal
# 1542| Type = [DoubleType] double
# 1542| ValueCategory = prvalue
# 1542| getInitializer(2): [ConstructorFieldInit] constructor init of field r
# 1542| Type = [LValueReferenceType] int &
# 1542| ValueCategory = prvalue
# 1542| getExpr(): [Literal] Unknown literal
# 1542| Type = [LValueReferenceType] int &
# 1542| ValueCategory = prvalue
# 1542| getEntryPoint(): [BlockStmt] { ... }
# 1542| getStmt(0): [ReturnStmt] return ...
# 1542| [MoveConstructor] void StructuredBindingTuple::StructuredBindingTuple(StructuredBindingTuple&&)
# 1542| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] StructuredBindingTuple &&
# 1548| [MemberFunction,TemplateFunction] type& StructuredBindingTuple::get<int i>()
# 1548| <params>:
# 1552| [FunctionTemplateSpecialization,MemberFunction] std::tuple_element<int 0, StructuredBindingTuple>::type& StructuredBindingTuple::get<int 0>()
# 1552| <params>:
# 1552| getEntryPoint(): [BlockStmt] { ... }
# 1552| getStmt(0): [ReturnStmt] return ...
# 1552| getExpr(): [PointerFieldAccess] i
# 1552| Type = [IntType] int
# 1552| ValueCategory = lvalue
# 1552| getQualifier(): [ThisExpr] this
# 1552| Type = [PointerType] StructuredBindingTuple *
# 1552| ValueCategory = prvalue(load)
#-----| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] int &
#-----| ValueCategory = prvalue
# 1554| [FunctionTemplateSpecialization,MemberFunction] std::tuple_element<int 1, StructuredBindingTuple>::type& StructuredBindingTuple::get<int 1>()
# 1554| <params>:
# 1554| getEntryPoint(): [BlockStmt] { ... }
# 1554| getStmt(0): [ReturnStmt] return ...
# 1554| getExpr(): [PointerFieldAccess] d
# 1554| Type = [DoubleType] double
# 1554| ValueCategory = lvalue
# 1554| getQualifier(): [ThisExpr] this
# 1554| Type = [PointerType] StructuredBindingTuple *
# 1554| ValueCategory = prvalue(load)
#-----| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] double &
#-----| ValueCategory = prvalue
# 1556| [FunctionTemplateSpecialization,MemberFunction] std::tuple_element<int 2, StructuredBindingTuple>::type StructuredBindingTuple::get<int 2>()
# 1556| <params>:
# 1556| getEntryPoint(): [BlockStmt] { ... }
# 1556| getStmt(0): [ReturnStmt] return ...
# 1556| getExpr(): [PointerFieldAccess] r
# 1556| Type = [LValueReferenceType] int &
# 1556| ValueCategory = prvalue(load)
# 1556| getQualifier(): [ThisExpr] this
# 1556| Type = [PointerType] StructuredBindingTuple *
# 1556| ValueCategory = prvalue(load)
# 1556| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1556| Type = [LValueReferenceType] int &
# 1556| ValueCategory = prvalue
# 1556| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1556| Type = [IntType] int
# 1556| ValueCategory = lvalue
# 1558| [TopLevelFunction] void tuple_structured_binding()
# 1558| <params>:
# 1558| getEntryPoint(): [BlockStmt] { ... }
# 1559| getStmt(0): [DeclStmt] declaration
# 1559| getDeclarationEntry(0): [VariableDeclarationEntry] definition of t
# 1559| Type = [Struct] StructuredBindingTuple
# 1559| getVariable().getInitializer(): [Initializer] initializer for t
# 1559| getExpr(): [ConstructorCall] call to StructuredBindingTuple
# 1559| Type = [VoidType] void
# 1559| ValueCategory = prvalue
# 1561| getStmt(1): [BlockStmt] { ... }
# 1562| getStmt(0): [DeclStmt] declaration
# 1562| getDeclarationEntry(0): (no string representation)
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| getVariable().getInitializer(): [Initializer] initializer for (unnamed local variable)
# 1562| getExpr(): [VariableAccess] t
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| ValueCategory = prvalue(load)
# 1562| getDeclarationEntry(1): [VariableDeclarationEntry] definition of i
# 1562| Type = [LValueReferenceType] type &
#-----| getVariable().getInitializer(): [Initializer] initializer for i
# 1562| getExpr(): [FunctionCall] call to get
# 1562| Type = [LValueReferenceType] type &
# 1562| ValueCategory = prvalue
# 1562| getQualifier(): [VariableAccess] (unnamed local variable)
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| ValueCategory = xvalue
# 1562| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1562| Type = [LValueReferenceType] type &
# 1562| ValueCategory = prvalue
# 1562| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1562| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1562| ValueCategory = lvalue
# 1562| getDeclarationEntry(2): [VariableDeclarationEntry] definition of d
# 1562| Type = [LValueReferenceType] type &
#-----| getVariable().getInitializer(): [Initializer] initializer for d
# 1562| getExpr(): [FunctionCall] call to get
# 1562| Type = [LValueReferenceType] type &
# 1562| ValueCategory = prvalue
# 1562| getQualifier(): [VariableAccess] (unnamed local variable)
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| ValueCategory = xvalue
# 1562| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1562| Type = [LValueReferenceType] type &
# 1562| ValueCategory = prvalue
# 1562| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1562| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1562| ValueCategory = lvalue
# 1562| getDeclarationEntry(3): [VariableDeclarationEntry] definition of r
# 1562| Type = [NestedTypedefType,UsingAliasTypedefType] type
#-----| getVariable().getInitializer(): [Initializer] initializer for r
# 1562| getExpr(): [FunctionCall] call to get
# 1562| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1562| ValueCategory = prvalue
# 1562| getQualifier(): [VariableAccess] (unnamed local variable)
# 1562| Type = [Struct] StructuredBindingTuple
# 1562| ValueCategory = xvalue
# 1562| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1562| Type = [LValueReferenceType] int &
# 1562| ValueCategory = prvalue
# 1562| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1562| Type = [IntType] int
# 1562| ValueCategory = lvalue
# 1563| getStmt(1): [ExprStmt] ExprStmt
# 1563| getExpr(): [AssignExpr] ... = ...
# 1563| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1563| ValueCategory = lvalue
# 1563| getLValue(): [VariableAccess] d
# 1563| Type = [LValueReferenceType] type &
# 1563| ValueCategory = prvalue(load)
# 1563| getRValue(): [Literal] 4.0
# 1563| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1563| Value = [Literal] 4.0
# 1563| ValueCategory = prvalue
# 1563| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1563| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1563| ValueCategory = lvalue
# 1564| getStmt(2): [DeclStmt] declaration
# 1564| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rd
# 1564| Type = [LValueReferenceType] double &
# 1564| getVariable().getInitializer(): [Initializer] initializer for rd
# 1564| getExpr(): [VariableAccess] d
# 1564| Type = [LValueReferenceType] type &
# 1564| ValueCategory = prvalue(load)
# 1564| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1564| Type = [LValueReferenceType] type &
# 1564| ValueCategory = prvalue
# 1564| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1564| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1564| ValueCategory = lvalue
# 1565| getStmt(3): [DeclStmt] declaration
# 1565| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v
# 1565| Type = [IntType] int
# 1565| getVariable().getInitializer(): [Initializer] initializer for v
# 1565| getExpr(): [VariableAccess] i
# 1565| Type = [LValueReferenceType] type &
# 1565| ValueCategory = prvalue(load)
# 1565| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1565| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1565| ValueCategory = prvalue(load)
# 1566| getStmt(4): [ExprStmt] ExprStmt
# 1566| getExpr(): [AssignExpr] ... = ...
# 1566| Type = [IntType] int
# 1566| ValueCategory = lvalue
# 1566| getLValue(): [VariableAccess] r
# 1566| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1566| ValueCategory = prvalue(load)
# 1566| getRValue(): [Literal] 5
# 1566| Type = [IntType] int
# 1566| Value = [Literal] 5
# 1566| ValueCategory = prvalue
# 1566| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1566| Type = [IntType] int
# 1566| ValueCategory = lvalue
# 1567| getStmt(5): [DeclStmt] declaration
# 1567| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rr
# 1567| Type = [LValueReferenceType] int &
# 1567| getVariable().getInitializer(): [Initializer] initializer for rr
# 1567| getExpr(): [VariableAccess] r
# 1567| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1567| ValueCategory = prvalue(load)
# 1567| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1567| Type = [LValueReferenceType] int &
# 1567| ValueCategory = prvalue
# 1567| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1567| Type = [IntType] int
# 1567| ValueCategory = lvalue
# 1568| getStmt(6): [DeclStmt] declaration
# 1568| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 1568| Type = [IntType] int
# 1568| getVariable().getInitializer(): [Initializer] initializer for w
# 1568| getExpr(): [VariableAccess] r
# 1568| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1568| ValueCategory = prvalue(load)
# 1568| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1568| Type = [IntType] int
# 1568| ValueCategory = prvalue(load)
# 1571| getStmt(2): [BlockStmt] { ... }
# 1572| getStmt(0): [DeclStmt] declaration
# 1572| getDeclarationEntry(0): [VariableDeclarationEntry] definition of unnamed_local_variable
# 1572| Type = [Struct] StructuredBindingTuple
# 1572| getVariable().getInitializer(): [Initializer] initializer for unnamed_local_variable
# 1572| getExpr(): [VariableAccess] t
# 1572| Type = [Struct] StructuredBindingTuple
# 1572| ValueCategory = prvalue(load)
# 1573| getStmt(1): [DeclStmt] declaration
# 1573| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 1573| Type = [LValueReferenceType] type &
# 1573| getVariable().getInitializer(): [Initializer] initializer for i
# 1573| getExpr(): [FunctionCall] call to get
# 1573| Type = [LValueReferenceType] type &
# 1573| ValueCategory = prvalue
# 1573| getQualifier(): [VariableAccess] unnamed_local_variable
# 1573| Type = [Struct] StructuredBindingTuple
# 1573| ValueCategory = lvalue
# 1573| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1573| Type = [LValueReferenceType] type &
# 1573| ValueCategory = prvalue
# 1573| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1573| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1573| ValueCategory = lvalue
# 1574| getStmt(2): [DeclStmt] declaration
# 1574| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
# 1574| Type = [LValueReferenceType] type &
# 1574| getVariable().getInitializer(): [Initializer] initializer for d
# 1574| getExpr(): [FunctionCall] call to get
# 1574| Type = [LValueReferenceType] type &
# 1574| ValueCategory = prvalue
# 1574| getQualifier(): [VariableAccess] unnamed_local_variable
# 1574| Type = [Struct] StructuredBindingTuple
# 1574| ValueCategory = lvalue
# 1574| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1574| Type = [LValueReferenceType] type &
# 1574| ValueCategory = prvalue
# 1574| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1574| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1574| ValueCategory = lvalue
# 1575| getStmt(3): [DeclStmt] declaration
# 1575| getDeclarationEntry(0): [VariableDeclarationEntry] definition of r
# 1575| Type = [LValueReferenceType] int &
# 1575| getVariable().getInitializer(): [Initializer] initializer for r
# 1575| getExpr(): [FunctionCall] call to get
# 1575| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1575| ValueCategory = prvalue
# 1575| getQualifier(): [VariableAccess] unnamed_local_variable
# 1575| Type = [Struct] StructuredBindingTuple
# 1575| ValueCategory = lvalue
# 1575| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1575| Type = [LValueReferenceType] int &
# 1575| ValueCategory = prvalue
# 1575| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1575| Type = [IntType] int
# 1575| ValueCategory = lvalue
# 1576| getStmt(4): [ExprStmt] ExprStmt
# 1576| getExpr(): [AssignExpr] ... = ...
# 1576| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1576| ValueCategory = lvalue
# 1576| getLValue(): [VariableAccess] d
# 1576| Type = [LValueReferenceType] type &
# 1576| ValueCategory = prvalue(load)
# 1576| getRValue(): [Literal] 4.0
# 1576| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1576| Value = [Literal] 4.0
# 1576| ValueCategory = prvalue
# 1576| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1576| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1576| ValueCategory = lvalue
# 1577| getStmt(5): [DeclStmt] declaration
# 1577| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rd
# 1577| Type = [LValueReferenceType] double &
# 1577| getVariable().getInitializer(): [Initializer] initializer for rd
# 1577| getExpr(): [VariableAccess] d
# 1577| Type = [LValueReferenceType] type &
# 1577| ValueCategory = prvalue(load)
# 1577| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1577| Type = [LValueReferenceType] type &
# 1577| ValueCategory = prvalue
# 1577| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1577| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1577| ValueCategory = lvalue
# 1578| getStmt(6): [DeclStmt] declaration
# 1578| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v
# 1578| Type = [IntType] int
# 1578| getVariable().getInitializer(): [Initializer] initializer for v
# 1578| getExpr(): [VariableAccess] i
# 1578| Type = [LValueReferenceType] type &
# 1578| ValueCategory = prvalue(load)
# 1578| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1578| Type = [NestedTypedefType,UsingAliasTypedefType] type
# 1578| ValueCategory = prvalue(load)
# 1579| getStmt(7): [ExprStmt] ExprStmt
# 1579| getExpr(): [AssignExpr] ... = ...
# 1579| Type = [IntType] int
# 1579| ValueCategory = lvalue
# 1579| getLValue(): [VariableAccess] r
# 1579| Type = [LValueReferenceType] int &
# 1579| ValueCategory = prvalue(load)
# 1579| getRValue(): [Literal] 5
# 1579| Type = [IntType] int
# 1579| Value = [Literal] 5
# 1579| ValueCategory = prvalue
# 1579| getLValue().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1579| Type = [IntType] int
# 1579| ValueCategory = lvalue
# 1580| getStmt(8): [DeclStmt] declaration
# 1580| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rr
# 1580| Type = [LValueReferenceType] int &
# 1580| getVariable().getInitializer(): [Initializer] initializer for rr
# 1580| getExpr(): [VariableAccess] r
# 1580| Type = [LValueReferenceType] int &
# 1580| ValueCategory = prvalue(load)
# 1580| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
# 1580| Type = [LValueReferenceType] int &
# 1580| ValueCategory = prvalue
# 1580| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
# 1580| Type = [IntType] int
# 1580| ValueCategory = lvalue
# 1581| getStmt(9): [DeclStmt] declaration
# 1581| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 1581| Type = [IntType] int
# 1581| getVariable().getInitializer(): [Initializer] initializer for w
# 1581| getExpr(): [VariableAccess] r
# 1581| Type = [LValueReferenceType] int &
# 1581| ValueCategory = prvalue(load)
# 1581| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1581| Type = [IntType] int
# 1581| ValueCategory = prvalue(load)
# 1583| getStmt(3): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -1458,4 +1458,128 @@ struct Inheritance_Test_A : public Inheritance_Test_B {
y = 3;
}
};
void array_structured_binding() {
int xs[2] = {1, 2};
// structured binding use
{
auto& [x0, x1] = xs;
x1 = 3;
int &rx1 = x1;
int x = x1;
}
// explicit reference version
{
auto& unnamed_local_variable = xs;
auto& x0 = xs[0];
auto& x1 = xs[1];
x1 = 3;
int &rx1 = x1;
int x = x1;
}
}
struct StructuredBindingDataMemberStruct {
int i = 1;
double d = 2.0;
unsigned int b : 3;
int& r = i;
};
void data_member_structured_binding() {
StructuredBindingDataMemberStruct s;
// structured binding use
{
auto [i, d, b, r] = s;
d = 4.0;
double& rd = d;
int v = i;
r = 5;
int& rr = r;
int w = r;
}
// explicit reference version
{
auto unnamed_local_variable = s;
auto& i = unnamed_local_variable.i;
auto& d = unnamed_local_variable.d;
// no equivalent for b
auto& r = unnamed_local_variable.r;
d = 4.0;
double& rd = d;
int v = i;
r = 5;
int& rr = r;
int w = r;
}
}
struct StructuredBindingTuple;
namespace std {
template<typename T>
struct tuple_size;
template<>
struct tuple_size<StructuredBindingTuple> {
static const unsigned int value = 3;
};
template<int, typename T>
struct tuple_element;
template<>
struct tuple_element<0, StructuredBindingTuple> {
using type = int;
};
template<>
struct tuple_element<1, StructuredBindingTuple> {
using type = double;
};
template<>
struct tuple_element<2, StructuredBindingTuple> {
using type = int&;
};
}
struct StructuredBindingTuple {
int i = 1;
double d = 2.2;
int& r = i;
template<int i>
typename std::tuple_element<i, StructuredBindingTuple>::type& get();
};
template<>
std::tuple_element<0, StructuredBindingTuple>::type& StructuredBindingTuple::get<0>() { return i; }
template<>
std::tuple_element<1, StructuredBindingTuple>::type& StructuredBindingTuple::get<1>() { return d; }
template<>
std::tuple_element<2, StructuredBindingTuple>::type& StructuredBindingTuple::get<2>() { return r; }
void tuple_structured_binding() {
StructuredBindingTuple t;
// structured binding use
{
auto [i, d, r] = t;
d = 4.0;
double& rd = d;
int v = i;
r = 5;
int& rr = r;
int w = r;
}
// explicit reference version
{
auto unnamed_local_variable = t;
auto& i = unnamed_local_variable.get<0>();
auto& d = unnamed_local_variable.get<1>();
auto& r = unnamed_local_variable.get<2>();
d = 4.0;
double& rd = d;
int v = i;
r = 5;
int& rr = r;
int w = r;
}
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -632,6 +632,7 @@
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_1 |
| file://:0:0:0:0 | Address | &:r0_2 |
| file://:0:0:0:0 | Address | &:r0_3 |
| file://:0:0:0:0 | Address | &:r0_3 |
@@ -653,6 +654,7 @@
| file://:0:0:0:0 | Address | &:r0_8 |
| file://:0:0:0:0 | Address | &:r0_8 |
| file://:0:0:0:0 | Address | &:r0_8 |
| file://:0:0:0:0 | Address | &:r0_8 |
| file://:0:0:0:0 | Address | &:r0_9 |
| file://:0:0:0:0 | Address | &:r0_9 |
| file://:0:0:0:0 | Address | &:r0_10 |
@@ -682,6 +684,8 @@
| file://:0:0:0:0 | ChiTotal | total:m763_8 |
| file://:0:0:0:0 | ChiTotal | total:m1043_10 |
| file://:0:0:0:0 | ChiTotal | total:m1240_4 |
| file://:0:0:0:0 | Left | r0_4 |
| file://:0:0:0:0 | Left | r0_11 |
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_2 |
| file://:0:0:0:0 | Load | m0_2 |
@@ -689,7 +693,11 @@
| file://:0:0:0:0 | Load | m745_6 |
| file://:0:0:0:0 | Load | m754_6 |
| file://:0:0:0:0 | Load | m763_6 |
| file://:0:0:0:0 | Load | m1466_4 |
| file://:0:0:0:0 | Load | m1466_4 |
| file://:0:0:0:0 | Load | ~m1444_6 |
| file://:0:0:0:0 | Right | r0_5 |
| file://:0:0:0:0 | Right | r0_12 |
| file://:0:0:0:0 | SideEffect | m0_4 |
| file://:0:0:0:0 | SideEffect | m0_4 |
| file://:0:0:0:0 | SideEffect | m0_4 |
@@ -715,11 +723,17 @@
| file://:0:0:0:0 | StoreValue | r0_1 |
| file://:0:0:0:0 | StoreValue | r0_1 |
| file://:0:0:0:0 | StoreValue | r0_1 |
| file://:0:0:0:0 | StoreValue | r0_1 |
| file://:0:0:0:0 | StoreValue | r0_1 |
| file://:0:0:0:0 | StoreValue | r0_3 |
| file://:0:0:0:0 | StoreValue | r0_6 |
| file://:0:0:0:0 | StoreValue | r0_13 |
| file://:0:0:0:0 | StoreValue | r0_13 |
| file://:0:0:0:0 | StoreValue | r0_22 |
| file://:0:0:0:0 | StoreValue | r0_22 |
| file://:0:0:0:0 | Unary | r0_1 |
| file://:0:0:0:0 | Unary | r0_2 |
| file://:0:0:0:0 | Unary | r0_3 |
| file://:0:0:0:0 | Unary | r0_5 |
| file://:0:0:0:0 | Unary | r0_5 |
| file://:0:0:0:0 | Unary | r0_6 |
@@ -730,6 +744,8 @@
| file://:0:0:0:0 | Unary | r0_7 |
| file://:0:0:0:0 | Unary | r0_8 |
| file://:0:0:0:0 | Unary | r0_9 |
| file://:0:0:0:0 | Unary | r0_9 |
| file://:0:0:0:0 | Unary | r0_10 |
| file://:0:0:0:0 | Unary | r0_10 |
| file://:0:0:0:0 | Unary | r0_11 |
| file://:0:0:0:0 | Unary | r0_12 |
@@ -6656,6 +6672,426 @@
| ir.cpp:1458:5:1458:9 | ChiPartial | partial:m1458_5 |
| ir.cpp:1458:5:1458:9 | ChiTotal | total:m1457_12 |
| ir.cpp:1458:9:1458:9 | StoreValue | r1458_1 |
| ir.cpp:1462:6:1462:29 | ChiPartial | partial:m1462_3 |
| ir.cpp:1462:6:1462:29 | ChiTotal | total:m1462_2 |
| ir.cpp:1462:6:1462:29 | SideEffect | m1462_3 |
| ir.cpp:1463:9:1463:10 | Address | &:r1463_1 |
| ir.cpp:1463:9:1463:10 | Left | r1463_1 |
| ir.cpp:1463:9:1463:10 | Left | r1463_1 |
| ir.cpp:1463:16:1463:22 | Address | &:r1463_4 |
| ir.cpp:1463:16:1463:22 | Address | &:r1463_9 |
| ir.cpp:1463:16:1463:22 | Right | r1463_3 |
| ir.cpp:1463:16:1463:22 | Right | r1463_8 |
| ir.cpp:1463:18:1463:18 | ChiPartial | partial:m1463_6 |
| ir.cpp:1463:18:1463:18 | ChiTotal | total:m1463_2 |
| ir.cpp:1463:18:1463:18 | StoreValue | r1463_5 |
| ir.cpp:1463:21:1463:21 | ChiPartial | partial:m1463_11 |
| ir.cpp:1463:21:1463:21 | ChiTotal | total:m1463_7 |
| ir.cpp:1463:21:1463:21 | StoreValue | r1463_10 |
| ir.cpp:1466:15:1466:15 | Address | &:r1466_1 |
| ir.cpp:1466:16:1466:16 | Address | &:r1466_5 |
| ir.cpp:1466:20:1466:20 | Address | &:r1466_6 |
| ir.cpp:1466:26:1466:27 | StoreValue | r1466_3 |
| ir.cpp:1466:26:1466:27 | Unary | r1466_2 |
| ir.cpp:1467:9:1467:10 | Address | &:r1467_2 |
| ir.cpp:1467:14:1467:14 | StoreValue | r1467_1 |
| ir.cpp:1468:14:1468:16 | Address | &:r1468_1 |
| ir.cpp:1468:20:1468:21 | StoreValue | r1468_3 |
| ir.cpp:1468:20:1468:21 | Unary | r1468_2 |
| ir.cpp:1469:13:1469:13 | Address | &:r1469_1 |
| ir.cpp:1469:17:1469:18 | Address | &:r1469_2 |
| ir.cpp:1469:17:1469:18 | Load | m1467_3 |
| ir.cpp:1469:17:1469:18 | StoreValue | r1469_3 |
| ir.cpp:1473:15:1473:36 | Address | &:r1473_1 |
| ir.cpp:1473:40:1473:41 | StoreValue | r1473_3 |
| ir.cpp:1473:40:1473:41 | Unary | r1473_2 |
| ir.cpp:1474:15:1474:16 | Address | &:r1474_1 |
| ir.cpp:1474:20:1474:21 | Left | r1474_3 |
| ir.cpp:1474:20:1474:21 | Unary | r1474_2 |
| ir.cpp:1474:20:1474:24 | StoreValue | r1474_6 |
| ir.cpp:1474:20:1474:24 | Unary | r1474_5 |
| ir.cpp:1474:23:1474:23 | Right | r1474_4 |
| ir.cpp:1475:15:1475:16 | Address | &:r1475_1 |
| ir.cpp:1475:20:1475:21 | Left | r1475_3 |
| ir.cpp:1475:20:1475:21 | Unary | r1475_2 |
| ir.cpp:1475:20:1475:24 | StoreValue | r1475_6 |
| ir.cpp:1475:20:1475:24 | Unary | r1475_5 |
| ir.cpp:1475:23:1475:23 | Right | r1475_4 |
| ir.cpp:1476:9:1476:10 | Address | &:r1476_2 |
| ir.cpp:1476:9:1476:10 | Address | &:r1476_4 |
| ir.cpp:1476:9:1476:10 | Load | m1475_7 |
| ir.cpp:1476:9:1476:10 | Unary | r1476_3 |
| ir.cpp:1476:9:1476:14 | ChiPartial | partial:m1476_5 |
| ir.cpp:1476:9:1476:14 | ChiTotal | total:m1463_12 |
| ir.cpp:1476:14:1476:14 | StoreValue | r1476_1 |
| ir.cpp:1477:14:1477:16 | Address | &:r1477_1 |
| ir.cpp:1477:20:1477:21 | Address | &:r1477_2 |
| ir.cpp:1477:20:1477:21 | Load | m1475_7 |
| ir.cpp:1477:20:1477:21 | StoreValue | r1477_5 |
| ir.cpp:1477:20:1477:21 | Unary | r1477_3 |
| ir.cpp:1477:20:1477:21 | Unary | r1477_4 |
| ir.cpp:1478:13:1478:13 | Address | &:r1478_1 |
| ir.cpp:1478:17:1478:18 | Address | &:r1478_2 |
| ir.cpp:1478:17:1478:18 | Address | &:r1478_3 |
| ir.cpp:1478:17:1478:18 | Load | m1475_7 |
| ir.cpp:1478:17:1478:18 | Load | m1476_5 |
| ir.cpp:1478:17:1478:18 | StoreValue | r1478_4 |
| ir.cpp:1482:8:1482:8 | Address | &:r1482_5 |
| ir.cpp:1482:8:1482:8 | Address | &:r1482_5 |
| ir.cpp:1482:8:1482:8 | Address | &:r1482_7 |
| ir.cpp:1482:8:1482:8 | Address | &:r1482_7 |
| ir.cpp:1482:8:1482:8 | ChiPartial | partial:m1482_3 |
| ir.cpp:1482:8:1482:8 | ChiTotal | total:m1482_2 |
| ir.cpp:1482:8:1482:8 | Load | m1482_6 |
| ir.cpp:1482:8:1482:8 | SideEffect | m1482_3 |
| ir.cpp:1482:8:1482:8 | SideEffect | m1482_8 |
| ir.cpp:1489:6:1489:35 | ChiPartial | partial:m1489_3 |
| ir.cpp:1489:6:1489:35 | ChiTotal | total:m1489_2 |
| ir.cpp:1489:6:1489:35 | SideEffect | ~m1511_6 |
| ir.cpp:1490:39:1490:39 | Address | &:r1490_1 |
| ir.cpp:1490:39:1490:39 | Address | &:r1490_1 |
| ir.cpp:1490:39:1490:39 | Arg(this) | this:r1490_1 |
| ir.cpp:1490:39:1490:39 | CallTarget | func:r1490_3 |
| ir.cpp:1490:39:1490:39 | ChiPartial | partial:m1490_5 |
| ir.cpp:1490:39:1490:39 | ChiPartial | partial:m1490_7 |
| ir.cpp:1490:39:1490:39 | ChiTotal | total:m1489_4 |
| ir.cpp:1490:39:1490:39 | ChiTotal | total:m1490_2 |
| ir.cpp:1490:39:1490:39 | SideEffect | ~m1489_4 |
| ir.cpp:1493:14:1493:14 | Address | &:r1493_1 |
| ir.cpp:1493:15:1493:15 | Address | &:r1493_5 |
| ir.cpp:1493:18:1493:18 | Address | &:r1493_9 |
| ir.cpp:1493:21:1493:21 | Address | &:r1493_13 |
| ir.cpp:1493:24:1493:24 | Address | &:r1493_17 |
| ir.cpp:1493:29:1493:29 | Address | &:r1493_2 |
| ir.cpp:1493:29:1493:29 | Load | m1490_8 |
| ir.cpp:1493:29:1493:29 | StoreValue | r1493_3 |
| ir.cpp:1493:30:1493:30 | Address | &:r1493_19 |
| ir.cpp:1493:30:1493:30 | Load | ~m1493_4 |
| ir.cpp:1493:30:1493:30 | StoreValue | r1493_7 |
| ir.cpp:1493:30:1493:30 | StoreValue | r1493_11 |
| ir.cpp:1493:30:1493:30 | StoreValue | r1493_15 |
| ir.cpp:1493:30:1493:30 | StoreValue | r1493_21 |
| ir.cpp:1493:30:1493:30 | Unary | r1493_6 |
| ir.cpp:1493:30:1493:30 | Unary | r1493_10 |
| ir.cpp:1493:30:1493:30 | Unary | r1493_14 |
| ir.cpp:1493:30:1493:30 | Unary | r1493_18 |
| ir.cpp:1493:30:1493:30 | Unary | r1493_20 |
| ir.cpp:1494:9:1494:9 | Address | &:r1494_2 |
| ir.cpp:1494:13:1494:15 | StoreValue | r1494_1 |
| ir.cpp:1495:17:1495:18 | Address | &:r1495_1 |
| ir.cpp:1495:22:1495:22 | StoreValue | r1495_3 |
| ir.cpp:1495:22:1495:22 | Unary | r1495_2 |
| ir.cpp:1496:13:1496:13 | Address | &:r1496_1 |
| ir.cpp:1496:17:1496:17 | Address | &:r1496_2 |
| ir.cpp:1496:17:1496:17 | Load | m1493_8 |
| ir.cpp:1496:17:1496:17 | StoreValue | r1496_3 |
| ir.cpp:1497:9:1497:9 | Address | &:r1497_2 |
| ir.cpp:1497:13:1497:13 | StoreValue | r1497_1 |
| ir.cpp:1498:14:1498:15 | Address | &:r1498_1 |
| ir.cpp:1498:19:1498:19 | StoreValue | r1498_3 |
| ir.cpp:1498:19:1498:19 | Unary | r1498_2 |
| ir.cpp:1499:13:1499:13 | Address | &:r1499_1 |
| ir.cpp:1499:17:1499:17 | Address | &:r1499_2 |
| ir.cpp:1499:17:1499:17 | Load | m1497_3 |
| ir.cpp:1499:17:1499:17 | StoreValue | r1499_3 |
| ir.cpp:1503:14:1503:35 | Address | &:r1503_1 |
| ir.cpp:1503:39:1503:39 | Address | &:r1503_2 |
| ir.cpp:1503:39:1503:39 | Load | m1490_8 |
| ir.cpp:1503:39:1503:39 | StoreValue | r1503_3 |
| ir.cpp:1504:15:1504:15 | Address | &:r1504_1 |
| ir.cpp:1504:19:1504:40 | Unary | r1504_2 |
| ir.cpp:1504:19:1504:42 | StoreValue | r1504_4 |
| ir.cpp:1504:42:1504:42 | Unary | r1504_3 |
| ir.cpp:1505:15:1505:15 | Address | &:r1505_1 |
| ir.cpp:1505:19:1505:40 | Unary | r1505_2 |
| ir.cpp:1505:19:1505:42 | StoreValue | r1505_4 |
| ir.cpp:1505:42:1505:42 | Unary | r1505_3 |
| ir.cpp:1507:15:1507:15 | Address | &:r1507_1 |
| ir.cpp:1507:19:1507:40 | Unary | r1507_2 |
| ir.cpp:1507:19:1507:42 | StoreValue | r1507_6 |
| ir.cpp:1507:19:1507:42 | Unary | r1507_5 |
| ir.cpp:1507:42:1507:42 | Address | &:r1507_3 |
| ir.cpp:1507:42:1507:42 | Load | ~m1503_4 |
| ir.cpp:1507:42:1507:42 | Unary | r1507_4 |
| ir.cpp:1508:9:1508:9 | Address | &:r1508_2 |
| ir.cpp:1508:9:1508:9 | Address | &:r1508_4 |
| ir.cpp:1508:9:1508:9 | Load | m1505_5 |
| ir.cpp:1508:9:1508:9 | Unary | r1508_3 |
| ir.cpp:1508:9:1508:15 | ChiPartial | partial:m1508_5 |
| ir.cpp:1508:9:1508:15 | ChiTotal | total:m1503_4 |
| ir.cpp:1508:13:1508:15 | StoreValue | r1508_1 |
| ir.cpp:1509:17:1509:18 | Address | &:r1509_1 |
| ir.cpp:1509:22:1509:22 | Address | &:r1509_2 |
| ir.cpp:1509:22:1509:22 | Load | m1505_5 |
| ir.cpp:1509:22:1509:22 | StoreValue | r1509_5 |
| ir.cpp:1509:22:1509:22 | Unary | r1509_3 |
| ir.cpp:1509:22:1509:22 | Unary | r1509_4 |
| ir.cpp:1510:13:1510:13 | Address | &:r1510_1 |
| ir.cpp:1510:17:1510:17 | Address | &:r1510_2 |
| ir.cpp:1510:17:1510:17 | Address | &:r1510_3 |
| ir.cpp:1510:17:1510:17 | Load | m1504_5 |
| ir.cpp:1510:17:1510:17 | Load | ~m1503_4 |
| ir.cpp:1510:17:1510:17 | StoreValue | r1510_4 |
| ir.cpp:1511:9:1511:9 | Address | &:r1511_2 |
| ir.cpp:1511:9:1511:9 | Address | &:r1511_4 |
| ir.cpp:1511:9:1511:9 | Load | m1507_7 |
| ir.cpp:1511:9:1511:9 | Unary | r1511_3 |
| ir.cpp:1511:9:1511:13 | ChiPartial | partial:m1511_5 |
| ir.cpp:1511:9:1511:13 | ChiTotal | total:m1490_6 |
| ir.cpp:1511:13:1511:13 | StoreValue | r1511_1 |
| ir.cpp:1512:14:1512:15 | Address | &:r1512_1 |
| ir.cpp:1512:19:1512:19 | Address | &:r1512_2 |
| ir.cpp:1512:19:1512:19 | Load | m1507_7 |
| ir.cpp:1512:19:1512:19 | StoreValue | r1512_5 |
| ir.cpp:1512:19:1512:19 | Unary | r1512_3 |
| ir.cpp:1512:19:1512:19 | Unary | r1512_4 |
| ir.cpp:1513:13:1513:13 | Address | &:r1513_1 |
| ir.cpp:1513:17:1513:17 | Address | &:r1513_2 |
| ir.cpp:1513:17:1513:17 | Address | &:r1513_3 |
| ir.cpp:1513:17:1513:17 | Load | m1507_7 |
| ir.cpp:1513:17:1513:17 | Load | ~m1511_6 |
| ir.cpp:1513:17:1513:17 | StoreValue | r1513_4 |
| ir.cpp:1542:8:1542:8 | Address | &:r1542_5 |
| ir.cpp:1542:8:1542:8 | Address | &:r1542_5 |
| ir.cpp:1542:8:1542:8 | Address | &:r1542_7 |
| ir.cpp:1542:8:1542:8 | Address | &:r1542_7 |
| ir.cpp:1542:8:1542:8 | ChiPartial | partial:m1542_3 |
| ir.cpp:1542:8:1542:8 | ChiTotal | total:m1542_2 |
| ir.cpp:1542:8:1542:8 | Load | m1542_6 |
| ir.cpp:1542:8:1542:8 | SideEffect | m1542_3 |
| ir.cpp:1542:8:1542:8 | SideEffect | m1542_8 |
| ir.cpp:1552:54:1552:83 | Address | &:r1552_5 |
| ir.cpp:1552:54:1552:83 | Address | &:r1552_5 |
| ir.cpp:1552:54:1552:83 | Address | &:r1552_7 |
| ir.cpp:1552:54:1552:83 | Address | &:r1552_7 |
| ir.cpp:1552:54:1552:83 | Address | &:r1552_14 |
| ir.cpp:1552:54:1552:83 | ChiPartial | partial:m1552_3 |
| ir.cpp:1552:54:1552:83 | ChiTotal | total:m1552_2 |
| ir.cpp:1552:54:1552:83 | Load | m0_2 |
| ir.cpp:1552:54:1552:83 | Load | m1552_6 |
| ir.cpp:1552:54:1552:83 | SideEffect | m1552_3 |
| ir.cpp:1552:54:1552:83 | SideEffect | m1552_8 |
| ir.cpp:1552:89:1552:97 | Address | &:r1552_9 |
| ir.cpp:1552:96:1552:96 | Address | &:r1552_10 |
| ir.cpp:1552:96:1552:96 | Load | m1552_6 |
| ir.cpp:1552:96:1552:96 | Unary | r1552_11 |
| ir.cpp:1552:96:1552:96 | Unary | r1552_12 |
| ir.cpp:1554:54:1554:83 | Address | &:r1554_5 |
| ir.cpp:1554:54:1554:83 | Address | &:r1554_5 |
| ir.cpp:1554:54:1554:83 | Address | &:r1554_7 |
| ir.cpp:1554:54:1554:83 | Address | &:r1554_7 |
| ir.cpp:1554:54:1554:83 | Address | &:r1554_14 |
| ir.cpp:1554:54:1554:83 | ChiPartial | partial:m1554_3 |
| ir.cpp:1554:54:1554:83 | ChiTotal | total:m1554_2 |
| ir.cpp:1554:54:1554:83 | Load | m0_2 |
| ir.cpp:1554:54:1554:83 | Load | m1554_6 |
| ir.cpp:1554:54:1554:83 | SideEffect | m1554_3 |
| ir.cpp:1554:54:1554:83 | SideEffect | m1554_8 |
| ir.cpp:1554:89:1554:97 | Address | &:r1554_9 |
| ir.cpp:1554:96:1554:96 | Address | &:r1554_10 |
| ir.cpp:1554:96:1554:96 | Load | m1554_6 |
| ir.cpp:1554:96:1554:96 | Unary | r1554_11 |
| ir.cpp:1554:96:1554:96 | Unary | r1554_12 |
| ir.cpp:1556:54:1556:83 | Address | &:r1556_5 |
| ir.cpp:1556:54:1556:83 | Address | &:r1556_5 |
| ir.cpp:1556:54:1556:83 | Address | &:r1556_7 |
| ir.cpp:1556:54:1556:83 | Address | &:r1556_7 |
| ir.cpp:1556:54:1556:83 | Address | &:r1556_18 |
| ir.cpp:1556:54:1556:83 | ChiPartial | partial:m1556_3 |
| ir.cpp:1556:54:1556:83 | ChiTotal | total:m1556_2 |
| ir.cpp:1556:54:1556:83 | Load | m1556_6 |
| ir.cpp:1556:54:1556:83 | Load | m1556_16 |
| ir.cpp:1556:54:1556:83 | SideEffect | m1556_3 |
| ir.cpp:1556:54:1556:83 | SideEffect | m1556_8 |
| ir.cpp:1556:89:1556:97 | Address | &:r1556_9 |
| ir.cpp:1556:96:1556:96 | Address | &:r1556_10 |
| ir.cpp:1556:96:1556:96 | Address | &:r1556_12 |
| ir.cpp:1556:96:1556:96 | Load | m1556_6 |
| ir.cpp:1556:96:1556:96 | Load | ~m1556_8 |
| ir.cpp:1556:96:1556:96 | StoreValue | r1556_15 |
| ir.cpp:1556:96:1556:96 | Unary | r1556_11 |
| ir.cpp:1556:96:1556:96 | Unary | r1556_13 |
| ir.cpp:1556:96:1556:96 | Unary | r1556_14 |
| ir.cpp:1558:6:1558:29 | ChiPartial | partial:m1558_3 |
| ir.cpp:1558:6:1558:29 | ChiTotal | total:m1558_2 |
| ir.cpp:1558:6:1558:29 | SideEffect | ~m1579_6 |
| ir.cpp:1559:28:1559:28 | Address | &:r1559_1 |
| ir.cpp:1559:28:1559:28 | Address | &:r1559_1 |
| ir.cpp:1559:28:1559:28 | Arg(this) | this:r1559_1 |
| ir.cpp:1559:28:1559:28 | CallTarget | func:r1559_3 |
| ir.cpp:1559:28:1559:28 | ChiPartial | partial:m1559_5 |
| ir.cpp:1559:28:1559:28 | ChiPartial | partial:m1559_7 |
| ir.cpp:1559:28:1559:28 | ChiTotal | total:m1558_4 |
| ir.cpp:1559:28:1559:28 | ChiTotal | total:m1559_2 |
| ir.cpp:1559:28:1559:28 | SideEffect | ~m1558_4 |
| ir.cpp:1562:14:1562:14 | Address | &:r1562_1 |
| ir.cpp:1562:14:1562:14 | Address | &:r1562_6 |
| ir.cpp:1562:14:1562:14 | Address | &:r1562_6 |
| ir.cpp:1562:14:1562:14 | Address | &:r1562_18 |
| ir.cpp:1562:14:1562:14 | Address | &:r1562_18 |
| ir.cpp:1562:14:1562:14 | Address | &:r1562_30 |
| ir.cpp:1562:14:1562:14 | Address | &:r1562_30 |
| ir.cpp:1562:14:1562:14 | Arg(this) | this:r1562_6 |
| ir.cpp:1562:14:1562:14 | Arg(this) | this:r1562_18 |
| ir.cpp:1562:14:1562:14 | Arg(this) | this:r1562_30 |
| ir.cpp:1562:14:1562:14 | CallTarget | func:r1562_7 |
| ir.cpp:1562:14:1562:14 | CallTarget | func:r1562_19 |
| ir.cpp:1562:14:1562:14 | CallTarget | func:r1562_31 |
| ir.cpp:1562:14:1562:14 | ChiPartial | partial:m1562_9 |
| ir.cpp:1562:14:1562:14 | ChiPartial | partial:m1562_12 |
| ir.cpp:1562:14:1562:14 | ChiPartial | partial:m1562_21 |
| ir.cpp:1562:14:1562:14 | ChiPartial | partial:m1562_24 |
| ir.cpp:1562:14:1562:14 | ChiPartial | partial:m1562_33 |
| ir.cpp:1562:14:1562:14 | ChiPartial | partial:m1562_36 |
| ir.cpp:1562:14:1562:14 | ChiTotal | total:m1559_6 |
| ir.cpp:1562:14:1562:14 | ChiTotal | total:m1562_4 |
| ir.cpp:1562:14:1562:14 | ChiTotal | total:m1562_10 |
| ir.cpp:1562:14:1562:14 | ChiTotal | total:m1562_13 |
| ir.cpp:1562:14:1562:14 | ChiTotal | total:m1562_22 |
| ir.cpp:1562:14:1562:14 | ChiTotal | total:m1562_25 |
| ir.cpp:1562:14:1562:14 | SideEffect | m1562_4 |
| ir.cpp:1562:14:1562:14 | SideEffect | m1562_13 |
| ir.cpp:1562:14:1562:14 | SideEffect | m1562_25 |
| ir.cpp:1562:14:1562:14 | SideEffect | ~m1559_6 |
| ir.cpp:1562:14:1562:14 | SideEffect | ~m1562_10 |
| ir.cpp:1562:14:1562:14 | SideEffect | ~m1562_22 |
| ir.cpp:1562:14:1562:14 | Unary | r1562_8 |
| ir.cpp:1562:14:1562:14 | Unary | r1562_20 |
| ir.cpp:1562:14:1562:14 | Unary | r1562_32 |
| ir.cpp:1562:14:1562:27 | StoreValue | r1562_15 |
| ir.cpp:1562:14:1562:27 | StoreValue | r1562_27 |
| ir.cpp:1562:14:1562:27 | StoreValue | r1562_39 |
| ir.cpp:1562:14:1562:27 | Unary | r1562_14 |
| ir.cpp:1562:14:1562:27 | Unary | r1562_26 |
| ir.cpp:1562:14:1562:27 | Unary | r1562_38 |
| ir.cpp:1562:15:1562:15 | Address | &:r1562_5 |
| ir.cpp:1562:18:1562:18 | Address | &:r1562_17 |
| ir.cpp:1562:21:1562:21 | Address | &:r1562_29 |
| ir.cpp:1562:26:1562:26 | Address | &:r1562_2 |
| ir.cpp:1562:26:1562:26 | Load | m1559_8 |
| ir.cpp:1562:26:1562:26 | StoreValue | r1562_3 |
| ir.cpp:1563:9:1563:9 | Address | &:r1563_2 |
| ir.cpp:1563:9:1563:9 | Address | &:r1563_4 |
| ir.cpp:1563:9:1563:9 | Load | m1562_28 |
| ir.cpp:1563:9:1563:9 | Unary | r1563_3 |
| ir.cpp:1563:9:1563:15 | ChiPartial | partial:m1563_5 |
| ir.cpp:1563:9:1563:15 | ChiTotal | total:m1562_37 |
| ir.cpp:1563:13:1563:15 | StoreValue | r1563_1 |
| ir.cpp:1564:17:1564:18 | Address | &:r1564_1 |
| ir.cpp:1564:22:1564:22 | Address | &:r1564_2 |
| ir.cpp:1564:22:1564:22 | Load | m1562_28 |
| ir.cpp:1564:22:1564:22 | StoreValue | r1564_5 |
| ir.cpp:1564:22:1564:22 | Unary | r1564_3 |
| ir.cpp:1564:22:1564:22 | Unary | r1564_4 |
| ir.cpp:1565:13:1565:13 | Address | &:r1565_1 |
| ir.cpp:1565:17:1565:17 | Address | &:r1565_2 |
| ir.cpp:1565:17:1565:17 | Address | &:r1565_3 |
| ir.cpp:1565:17:1565:17 | Load | m1562_16 |
| ir.cpp:1565:17:1565:17 | Load | ~m1562_37 |
| ir.cpp:1565:17:1565:17 | StoreValue | r1565_4 |
| ir.cpp:1566:9:1566:9 | Address | &:r1566_2 |
| ir.cpp:1566:9:1566:9 | Address | &:r1566_4 |
| ir.cpp:1566:9:1566:9 | Load | m1562_40 |
| ir.cpp:1566:9:1566:9 | Unary | r1566_3 |
| ir.cpp:1566:9:1566:13 | ChiPartial | partial:m1566_5 |
| ir.cpp:1566:9:1566:13 | ChiTotal | total:m1562_34 |
| ir.cpp:1566:13:1566:13 | StoreValue | r1566_1 |
| ir.cpp:1567:14:1567:15 | Address | &:r1567_1 |
| ir.cpp:1567:19:1567:19 | Address | &:r1567_2 |
| ir.cpp:1567:19:1567:19 | Load | m1562_40 |
| ir.cpp:1567:19:1567:19 | StoreValue | r1567_5 |
| ir.cpp:1567:19:1567:19 | Unary | r1567_3 |
| ir.cpp:1567:19:1567:19 | Unary | r1567_4 |
| ir.cpp:1568:13:1568:13 | Address | &:r1568_1 |
| ir.cpp:1568:17:1568:17 | Address | &:r1568_2 |
| ir.cpp:1568:17:1568:17 | Address | &:r1568_3 |
| ir.cpp:1568:17:1568:17 | Load | m1562_40 |
| ir.cpp:1568:17:1568:17 | Load | ~m1566_6 |
| ir.cpp:1568:17:1568:17 | StoreValue | r1568_4 |
| ir.cpp:1572:14:1572:35 | Address | &:r1572_1 |
| ir.cpp:1572:39:1572:39 | Address | &:r1572_2 |
| ir.cpp:1572:39:1572:39 | Load | m1559_8 |
| ir.cpp:1572:39:1572:39 | StoreValue | r1572_3 |
| ir.cpp:1573:15:1573:15 | Address | &:r1573_1 |
| ir.cpp:1573:19:1573:40 | Address | &:r1573_2 |
| ir.cpp:1573:19:1573:40 | Address | &:r1573_2 |
| ir.cpp:1573:19:1573:40 | Arg(this) | this:r1573_2 |
| ir.cpp:1573:19:1573:40 | ChiPartial | partial:m1573_8 |
| ir.cpp:1573:19:1573:40 | ChiTotal | total:m1572_4 |
| ir.cpp:1573:19:1573:40 | SideEffect | m1572_4 |
| ir.cpp:1573:42:1573:47 | CallTarget | func:r1573_3 |
| ir.cpp:1573:42:1573:47 | ChiPartial | partial:m1573_5 |
| ir.cpp:1573:42:1573:47 | ChiTotal | total:m1566_6 |
| ir.cpp:1573:42:1573:47 | SideEffect | ~m1566_6 |
| ir.cpp:1573:42:1573:47 | Unary | r1573_4 |
| ir.cpp:1573:42:1573:50 | StoreValue | r1573_11 |
| ir.cpp:1573:42:1573:50 | Unary | r1573_10 |
| ir.cpp:1574:15:1574:15 | Address | &:r1574_1 |
| ir.cpp:1574:19:1574:40 | Address | &:r1574_2 |
| ir.cpp:1574:19:1574:40 | Address | &:r1574_2 |
| ir.cpp:1574:19:1574:40 | Arg(this) | this:r1574_2 |
| ir.cpp:1574:19:1574:40 | ChiPartial | partial:m1574_8 |
| ir.cpp:1574:19:1574:40 | ChiTotal | total:m1573_9 |
| ir.cpp:1574:19:1574:40 | SideEffect | m1573_9 |
| ir.cpp:1574:42:1574:47 | CallTarget | func:r1574_3 |
| ir.cpp:1574:42:1574:47 | ChiPartial | partial:m1574_5 |
| ir.cpp:1574:42:1574:47 | ChiTotal | total:m1573_6 |
| ir.cpp:1574:42:1574:47 | SideEffect | ~m1573_6 |
| ir.cpp:1574:42:1574:47 | Unary | r1574_4 |
| ir.cpp:1574:42:1574:50 | StoreValue | r1574_11 |
| ir.cpp:1574:42:1574:50 | Unary | r1574_10 |
| ir.cpp:1575:15:1575:15 | Address | &:r1575_1 |
| ir.cpp:1575:19:1575:40 | Address | &:r1575_2 |
| ir.cpp:1575:19:1575:40 | Address | &:r1575_2 |
| ir.cpp:1575:19:1575:40 | Arg(this) | this:r1575_2 |
| ir.cpp:1575:19:1575:40 | ChiPartial | partial:m1575_8 |
| ir.cpp:1575:19:1575:40 | ChiTotal | total:m1574_9 |
| ir.cpp:1575:19:1575:40 | SideEffect | m1574_9 |
| ir.cpp:1575:42:1575:47 | CallTarget | func:r1575_3 |
| ir.cpp:1575:42:1575:47 | ChiPartial | partial:m1575_5 |
| ir.cpp:1575:42:1575:47 | ChiTotal | total:m1574_6 |
| ir.cpp:1575:42:1575:47 | SideEffect | ~m1574_6 |
| ir.cpp:1575:42:1575:47 | Unary | r1575_4 |
| ir.cpp:1575:42:1575:50 | StoreValue | r1575_11 |
| ir.cpp:1575:42:1575:50 | Unary | r1575_10 |
| ir.cpp:1576:9:1576:9 | Address | &:r1576_2 |
| ir.cpp:1576:9:1576:9 | Address | &:r1576_4 |
| ir.cpp:1576:9:1576:9 | Load | m1574_12 |
| ir.cpp:1576:9:1576:9 | Unary | r1576_3 |
| ir.cpp:1576:9:1576:15 | ChiPartial | partial:m1576_5 |
| ir.cpp:1576:9:1576:15 | ChiTotal | total:m1575_9 |
| ir.cpp:1576:13:1576:15 | StoreValue | r1576_1 |
| ir.cpp:1577:17:1577:18 | Address | &:r1577_1 |
| ir.cpp:1577:22:1577:22 | Address | &:r1577_2 |
| ir.cpp:1577:22:1577:22 | Load | m1574_12 |
| ir.cpp:1577:22:1577:22 | StoreValue | r1577_5 |
| ir.cpp:1577:22:1577:22 | Unary | r1577_3 |
| ir.cpp:1577:22:1577:22 | Unary | r1577_4 |
| ir.cpp:1578:13:1578:13 | Address | &:r1578_1 |
| ir.cpp:1578:17:1578:17 | Address | &:r1578_2 |
| ir.cpp:1578:17:1578:17 | Address | &:r1578_3 |
| ir.cpp:1578:17:1578:17 | Load | m1573_12 |
| ir.cpp:1578:17:1578:17 | Load | ~m1575_9 |
| ir.cpp:1578:17:1578:17 | StoreValue | r1578_4 |
| ir.cpp:1579:9:1579:9 | Address | &:r1579_2 |
| ir.cpp:1579:9:1579:9 | Address | &:r1579_4 |
| ir.cpp:1579:9:1579:9 | Load | m1575_12 |
| ir.cpp:1579:9:1579:9 | Unary | r1579_3 |
| ir.cpp:1579:9:1579:13 | ChiPartial | partial:m1579_5 |
| ir.cpp:1579:9:1579:13 | ChiTotal | total:m1575_6 |
| ir.cpp:1579:13:1579:13 | StoreValue | r1579_1 |
| ir.cpp:1580:14:1580:15 | Address | &:r1580_1 |
| ir.cpp:1580:19:1580:19 | Address | &:r1580_2 |
| ir.cpp:1580:19:1580:19 | Load | m1575_12 |
| ir.cpp:1580:19:1580:19 | StoreValue | r1580_5 |
| ir.cpp:1580:19:1580:19 | Unary | r1580_3 |
| ir.cpp:1580:19:1580:19 | Unary | r1580_4 |
| ir.cpp:1581:13:1581:13 | Address | &:r1581_1 |
| ir.cpp:1581:17:1581:17 | Address | &:r1581_2 |
| ir.cpp:1581:17:1581:17 | Address | &:r1581_3 |
| ir.cpp:1581:17:1581:17 | Load | m1575_12 |
| ir.cpp:1581:17:1581:17 | Load | ~m1579_6 |
| ir.cpp:1581:17:1581:17 | StoreValue | r1581_4 |
| 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 |

View File

@@ -7896,6 +7896,447 @@ ir.cpp:
# 1457| v1457_13(void) = AliasedUse : ~m?
# 1457| v1457_14(void) = ExitFunction :
# 1462| void array_structured_binding()
# 1462| Block 0
# 1462| v1462_1(void) = EnterFunction :
# 1462| mu1462_2(unknown) = AliasedDefinition :
# 1462| mu1462_3(unknown) = InitializeNonLocal :
# 1463| r1463_1(glval<int[2]>) = VariableAddress[xs] :
# 1463| mu1463_2(int[2]) = Uninitialized[xs] : &:r1463_1
# 1463| r1463_3(int) = Constant[0] :
# 1463| r1463_4(glval<int>) = PointerAdd[4] : r1463_1, r1463_3
# 1463| r1463_5(int) = Constant[1] :
# 1463| mu1463_6(int) = Store[?] : &:r1463_4, r1463_5
# 1463| r1463_7(int) = Constant[1] :
# 1463| r1463_8(glval<int>) = PointerAdd[4] : r1463_1, r1463_7
# 1463| r1463_9(int) = Constant[2] :
# 1463| mu1463_10(int) = Store[?] : &:r1463_8, r1463_9
# 1466| r1466_1(glval<int(&)[2]>) = VariableAddress[(unnamed local variable)] :
# 1466| r1466_2(glval<int[2]>) = VariableAddress[xs] :
# 1466| r1466_3(int(&)[2]) = CopyValue : r1466_2
# 1466| mu1466_4(int(&)[2]) = Store[(unnamed local variable)] : &:r1466_1, r1466_3
# 1466| r1466_5(glval<int>) = VariableAddress[x0] :
#-----| r0_1(glval<int(&)[2]>) = VariableAddress[(unnamed local variable)] :
#-----| r0_2(int(&)[2]) = Load[(unnamed local variable)] : &:r0_1, ~m?
#-----| r0_3(glval<int[2]>) = CopyValue : r0_2
#-----| r0_4(int *) = Convert : r0_3
#-----| r0_5(unsigned long) = Constant[0] :
#-----| r0_6(glval<int>) = PointerAdd[4] : r0_4, r0_5
#-----| mu0_7(int) = Store[x0] : &:r1466_5, r0_6
# 1466| r1466_6(glval<int>) = VariableAddress[x1] :
#-----| r0_8(glval<int(&)[2]>) = VariableAddress[(unnamed local variable)] :
#-----| r0_9(int(&)[2]) = Load[(unnamed local variable)] : &:r0_8, ~m?
#-----| r0_10(glval<int[2]>) = CopyValue : r0_9
#-----| r0_11(int *) = Convert : r0_10
#-----| r0_12(unsigned long) = Constant[1] :
#-----| r0_13(glval<int>) = PointerAdd[4] : r0_11, r0_12
#-----| mu0_14(int) = Store[x1] : &:r1466_6, r0_13
# 1467| r1467_1(int) = Constant[3] :
# 1467| r1467_2(glval<int>) = VariableAddress[x1] :
# 1467| mu1467_3(int) = Store[x1] : &:r1467_2, r1467_1
# 1468| r1468_1(glval<int &>) = VariableAddress[rx1] :
# 1468| r1468_2(glval<int>) = VariableAddress[x1] :
# 1468| r1468_3(int &) = CopyValue : r1468_2
# 1468| mu1468_4(int &) = Store[rx1] : &:r1468_1, r1468_3
# 1469| r1469_1(glval<int>) = VariableAddress[x] :
# 1469| r1469_2(glval<int>) = VariableAddress[x1] :
# 1469| r1469_3(int) = Load[x1] : &:r1469_2, ~m?
# 1469| mu1469_4(int) = Store[x] : &:r1469_1, r1469_3
# 1473| r1473_1(glval<int(&)[2]>) = VariableAddress[unnamed_local_variable] :
# 1473| r1473_2(glval<int[2]>) = VariableAddress[xs] :
# 1473| r1473_3(int(&)[2]) = CopyValue : r1473_2
# 1473| mu1473_4(int(&)[2]) = Store[unnamed_local_variable] : &:r1473_1, r1473_3
# 1474| r1474_1(glval<int &>) = VariableAddress[x0] :
# 1474| r1474_2(glval<int[2]>) = VariableAddress[xs] :
# 1474| r1474_3(int *) = Convert : r1474_2
# 1474| r1474_4(int) = Constant[0] :
# 1474| r1474_5(glval<int>) = PointerAdd[4] : r1474_3, r1474_4
# 1474| r1474_6(int &) = CopyValue : r1474_5
# 1474| mu1474_7(int &) = Store[x0] : &:r1474_1, r1474_6
# 1475| r1475_1(glval<int &>) = VariableAddress[x1] :
# 1475| r1475_2(glval<int[2]>) = VariableAddress[xs] :
# 1475| r1475_3(int *) = Convert : r1475_2
# 1475| r1475_4(int) = Constant[1] :
# 1475| r1475_5(glval<int>) = PointerAdd[4] : r1475_3, r1475_4
# 1475| r1475_6(int &) = CopyValue : r1475_5
# 1475| mu1475_7(int &) = Store[x1] : &:r1475_1, r1475_6
# 1476| r1476_1(int) = Constant[3] :
# 1476| r1476_2(glval<int &>) = VariableAddress[x1] :
# 1476| r1476_3(int &) = Load[x1] : &:r1476_2, ~m?
# 1476| r1476_4(glval<int>) = CopyValue : r1476_3
# 1476| mu1476_5(int) = Store[?] : &:r1476_4, r1476_1
# 1477| r1477_1(glval<int &>) = VariableAddress[rx1] :
# 1477| r1477_2(glval<int &>) = VariableAddress[x1] :
# 1477| r1477_3(int &) = Load[x1] : &:r1477_2, ~m?
# 1477| r1477_4(glval<int>) = CopyValue : r1477_3
# 1477| r1477_5(int &) = CopyValue : r1477_4
# 1477| mu1477_6(int &) = Store[rx1] : &:r1477_1, r1477_5
# 1478| r1478_1(glval<int>) = VariableAddress[x] :
# 1478| r1478_2(glval<int &>) = VariableAddress[x1] :
# 1478| r1478_3(int &) = Load[x1] : &:r1478_2, ~m?
# 1478| r1478_4(int) = Load[?] : &:r1478_3, ~m?
# 1478| mu1478_5(int) = Store[x] : &:r1478_1, r1478_4
# 1480| v1480_1(void) = NoOp :
# 1462| v1462_4(void) = ReturnVoid :
# 1462| v1462_5(void) = AliasedUse : ~m?
# 1462| v1462_6(void) = ExitFunction :
# 1482| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct()
# 1482| Block 0
# 1482| v1482_1(void) = EnterFunction :
# 1482| mu1482_2(unknown) = AliasedDefinition :
# 1482| mu1482_3(unknown) = InitializeNonLocal :
# 1482| r1482_4(glval<unknown>) = VariableAddress[#this] :
# 1482| mu1482_5(glval<StructuredBindingDataMemberStruct>) = InitializeParameter[#this] : &:r1482_4
# 1482| r1482_6(glval<StructuredBindingDataMemberStruct>) = Load[#this] : &:r1482_4, ~m?
# 1482| mu1482_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1482_6
# 1482| v1482_8(void) = NoOp :
# 1482| v1482_9(void) = ReturnIndirection[#this] : &:r1482_6, ~m?
# 1482| v1482_10(void) = ReturnVoid :
# 1482| v1482_11(void) = AliasedUse : ~m?
# 1482| v1482_12(void) = ExitFunction :
# 1489| void data_member_structured_binding()
# 1489| Block 0
# 1489| v1489_1(void) = EnterFunction :
# 1489| mu1489_2(unknown) = AliasedDefinition :
# 1489| mu1489_3(unknown) = InitializeNonLocal :
# 1490| r1490_1(glval<StructuredBindingDataMemberStruct>) = VariableAddress[s] :
# 1490| mu1490_2(StructuredBindingDataMemberStruct) = Uninitialized[s] : &:r1490_1
# 1490| r1490_3(glval<unknown>) = FunctionAddress[StructuredBindingDataMemberStruct] :
# 1490| v1490_4(void) = Call[StructuredBindingDataMemberStruct] : func:r1490_3, this:r1490_1
# 1490| mu1490_5(unknown) = ^CallSideEffect : ~m?
# 1490| mu1490_6(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1490_1
# 1493| r1493_1(glval<StructuredBindingDataMemberStruct>) = VariableAddress[(unnamed local variable)] :
# 1493| r1493_2(glval<StructuredBindingDataMemberStruct>) = VariableAddress[s] :
# 1493| r1493_3(StructuredBindingDataMemberStruct) = Load[s] : &:r1493_2, ~m?
# 1493| mu1493_4(StructuredBindingDataMemberStruct) = Store[(unnamed local variable)] : &:r1493_1, r1493_3
# 1493| r1493_5(glval<int>) = VariableAddress[i] :
# 1493| r1493_6(glval<StructuredBindingDataMemberStruct>) = VariableAddress[(unnamed local variable)] :
# 1493| r1493_7(glval<int>) = FieldAddress[i] : r1493_6
# 1493| mu1493_8(int) = Store[i] : &:r1493_5, r1493_7
# 1493| r1493_9(glval<double>) = VariableAddress[d] :
# 1493| r1493_10(glval<StructuredBindingDataMemberStruct>) = VariableAddress[(unnamed local variable)] :
# 1493| r1493_11(glval<double>) = FieldAddress[d] : r1493_10
# 1493| mu1493_12(double) = Store[d] : &:r1493_9, r1493_11
# 1493| r1493_13(glval<unsigned int>) = VariableAddress[b] :
# 1493| r1493_14(glval<StructuredBindingDataMemberStruct>) = VariableAddress[(unnamed local variable)] :
# 1493| r1493_15(glval<unsigned int>) = FieldAddress[b] : r1493_14
# 1493| mu1493_16(unsigned int) = Store[b] : &:r1493_13, r1493_15
# 1493| r1493_17(glval<int>) = VariableAddress[r] :
# 1493| r1493_18(glval<StructuredBindingDataMemberStruct>) = VariableAddress[(unnamed local variable)] :
# 1493| r1493_19(glval<int &>) = FieldAddress[r] : r1493_18
# 1493| r1493_20(int &) = Load[?] : &:r1493_19, ~m?
# 1493| r1493_21(glval<int>) = CopyValue : r1493_20
# 1493| mu1493_22(int) = Store[r] : &:r1493_17, r1493_21
# 1494| r1494_1(double) = Constant[4.0] :
# 1494| r1494_2(glval<double>) = VariableAddress[d] :
# 1494| mu1494_3(double) = Store[d] : &:r1494_2, r1494_1
# 1495| r1495_1(glval<double &>) = VariableAddress[rd] :
# 1495| r1495_2(glval<double>) = VariableAddress[d] :
# 1495| r1495_3(double &) = CopyValue : r1495_2
# 1495| mu1495_4(double &) = Store[rd] : &:r1495_1, r1495_3
# 1496| r1496_1(glval<int>) = VariableAddress[v] :
# 1496| r1496_2(glval<int>) = VariableAddress[i] :
# 1496| r1496_3(int) = Load[i] : &:r1496_2, ~m?
# 1496| mu1496_4(int) = Store[v] : &:r1496_1, r1496_3
# 1497| r1497_1(int) = Constant[5] :
# 1497| r1497_2(glval<int>) = VariableAddress[r] :
# 1497| mu1497_3(int) = Store[r] : &:r1497_2, r1497_1
# 1498| r1498_1(glval<int &>) = VariableAddress[rr] :
# 1498| r1498_2(glval<int>) = VariableAddress[r] :
# 1498| r1498_3(int &) = CopyValue : r1498_2
# 1498| mu1498_4(int &) = Store[rr] : &:r1498_1, r1498_3
# 1499| r1499_1(glval<int>) = VariableAddress[w] :
# 1499| r1499_2(glval<int>) = VariableAddress[r] :
# 1499| r1499_3(int) = Load[r] : &:r1499_2, ~m?
# 1499| mu1499_4(int) = Store[w] : &:r1499_1, r1499_3
# 1503| r1503_1(glval<StructuredBindingDataMemberStruct>) = VariableAddress[unnamed_local_variable] :
# 1503| r1503_2(glval<StructuredBindingDataMemberStruct>) = VariableAddress[s] :
# 1503| r1503_3(StructuredBindingDataMemberStruct) = Load[s] : &:r1503_2, ~m?
# 1503| mu1503_4(StructuredBindingDataMemberStruct) = Store[unnamed_local_variable] : &:r1503_1, r1503_3
# 1504| r1504_1(glval<int &>) = VariableAddress[i] :
# 1504| r1504_2(glval<StructuredBindingDataMemberStruct>) = VariableAddress[unnamed_local_variable] :
# 1504| r1504_3(glval<int>) = FieldAddress[i] : r1504_2
# 1504| r1504_4(int &) = CopyValue : r1504_3
# 1504| mu1504_5(int &) = Store[i] : &:r1504_1, r1504_4
# 1505| r1505_1(glval<double &>) = VariableAddress[d] :
# 1505| r1505_2(glval<StructuredBindingDataMemberStruct>) = VariableAddress[unnamed_local_variable] :
# 1505| r1505_3(glval<double>) = FieldAddress[d] : r1505_2
# 1505| r1505_4(double &) = CopyValue : r1505_3
# 1505| mu1505_5(double &) = Store[d] : &:r1505_1, r1505_4
# 1507| r1507_1(glval<int &>) = VariableAddress[r] :
# 1507| r1507_2(glval<StructuredBindingDataMemberStruct>) = VariableAddress[unnamed_local_variable] :
# 1507| r1507_3(glval<int &>) = FieldAddress[r] : r1507_2
# 1507| r1507_4(int &) = Load[?] : &:r1507_3, ~m?
# 1507| r1507_5(glval<int>) = CopyValue : r1507_4
# 1507| r1507_6(int &) = CopyValue : r1507_5
# 1507| mu1507_7(int &) = Store[r] : &:r1507_1, r1507_6
# 1508| r1508_1(double) = Constant[4.0] :
# 1508| r1508_2(glval<double &>) = VariableAddress[d] :
# 1508| r1508_3(double &) = Load[d] : &:r1508_2, ~m?
# 1508| r1508_4(glval<double>) = CopyValue : r1508_3
# 1508| mu1508_5(double) = Store[?] : &:r1508_4, r1508_1
# 1509| r1509_1(glval<double &>) = VariableAddress[rd] :
# 1509| r1509_2(glval<double &>) = VariableAddress[d] :
# 1509| r1509_3(double &) = Load[d] : &:r1509_2, ~m?
# 1509| r1509_4(glval<double>) = CopyValue : r1509_3
# 1509| r1509_5(double &) = CopyValue : r1509_4
# 1509| mu1509_6(double &) = Store[rd] : &:r1509_1, r1509_5
# 1510| r1510_1(glval<int>) = VariableAddress[v] :
# 1510| r1510_2(glval<int &>) = VariableAddress[i] :
# 1510| r1510_3(int &) = Load[i] : &:r1510_2, ~m?
# 1510| r1510_4(int) = Load[?] : &:r1510_3, ~m?
# 1510| mu1510_5(int) = Store[v] : &:r1510_1, r1510_4
# 1511| r1511_1(int) = Constant[5] :
# 1511| r1511_2(glval<int &>) = VariableAddress[r] :
# 1511| r1511_3(int &) = Load[r] : &:r1511_2, ~m?
# 1511| r1511_4(glval<int>) = CopyValue : r1511_3
# 1511| mu1511_5(int) = Store[?] : &:r1511_4, r1511_1
# 1512| r1512_1(glval<int &>) = VariableAddress[rr] :
# 1512| r1512_2(glval<int &>) = VariableAddress[r] :
# 1512| r1512_3(int &) = Load[r] : &:r1512_2, ~m?
# 1512| r1512_4(glval<int>) = CopyValue : r1512_3
# 1512| r1512_5(int &) = CopyValue : r1512_4
# 1512| mu1512_6(int &) = Store[rr] : &:r1512_1, r1512_5
# 1513| r1513_1(glval<int>) = VariableAddress[w] :
# 1513| r1513_2(glval<int &>) = VariableAddress[r] :
# 1513| r1513_3(int &) = Load[r] : &:r1513_2, ~m?
# 1513| r1513_4(int) = Load[?] : &:r1513_3, ~m?
# 1513| mu1513_5(int) = Store[w] : &:r1513_1, r1513_4
# 1515| v1515_1(void) = NoOp :
# 1489| v1489_4(void) = ReturnVoid :
# 1489| v1489_5(void) = AliasedUse : ~m?
# 1489| v1489_6(void) = ExitFunction :
# 1542| void StructuredBindingTuple::StructuredBindingTuple()
# 1542| Block 0
# 1542| v1542_1(void) = EnterFunction :
# 1542| mu1542_2(unknown) = AliasedDefinition :
# 1542| mu1542_3(unknown) = InitializeNonLocal :
# 1542| r1542_4(glval<unknown>) = VariableAddress[#this] :
# 1542| mu1542_5(glval<StructuredBindingTuple>) = InitializeParameter[#this] : &:r1542_4
# 1542| r1542_6(glval<StructuredBindingTuple>) = Load[#this] : &:r1542_4, ~m?
# 1542| mu1542_7(StructuredBindingTuple) = InitializeIndirection[#this] : &:r1542_6
# 1542| v1542_8(void) = NoOp :
# 1542| v1542_9(void) = ReturnIndirection[#this] : &:r1542_6, ~m?
# 1542| v1542_10(void) = ReturnVoid :
# 1542| v1542_11(void) = AliasedUse : ~m?
# 1542| v1542_12(void) = ExitFunction :
# 1552| std::tuple_element<int 0, StructuredBindingTuple>::type& StructuredBindingTuple::get<int 0>()
# 1552| Block 0
# 1552| v1552_1(void) = EnterFunction :
# 1552| mu1552_2(unknown) = AliasedDefinition :
# 1552| mu1552_3(unknown) = InitializeNonLocal :
# 1552| r1552_4(glval<unknown>) = VariableAddress[#this] :
# 1552| mu1552_5(glval<StructuredBindingTuple>) = InitializeParameter[#this] : &:r1552_4
# 1552| r1552_6(glval<StructuredBindingTuple>) = Load[#this] : &:r1552_4, ~m?
# 1552| mu1552_7(StructuredBindingTuple) = InitializeIndirection[#this] : &:r1552_6
# 1552| r1552_8(glval<int &>) = VariableAddress[#return] :
# 1552| r1552_9(glval<unknown>) = VariableAddress[#this] :
# 1552| r1552_10(StructuredBindingTuple *) = Load[#this] : &:r1552_9, ~m?
# 1552| r1552_11(glval<int>) = FieldAddress[i] : r1552_10
#-----| r0_1(int &) = CopyValue : r1552_11
#-----| mu0_2(int &) = Store[#return] : &:r1552_8, r0_1
# 1552| v1552_12(void) = ReturnIndirection[#this] : &:r1552_6, ~m?
# 1552| r1552_13(glval<int &>) = VariableAddress[#return] :
# 1552| v1552_14(void) = ReturnValue : &:r1552_13, ~m?
# 1552| v1552_15(void) = AliasedUse : ~m?
# 1552| v1552_16(void) = ExitFunction :
# 1554| std::tuple_element<int 1, StructuredBindingTuple>::type& StructuredBindingTuple::get<int 1>()
# 1554| Block 0
# 1554| v1554_1(void) = EnterFunction :
# 1554| mu1554_2(unknown) = AliasedDefinition :
# 1554| mu1554_3(unknown) = InitializeNonLocal :
# 1554| r1554_4(glval<unknown>) = VariableAddress[#this] :
# 1554| mu1554_5(glval<StructuredBindingTuple>) = InitializeParameter[#this] : &:r1554_4
# 1554| r1554_6(glval<StructuredBindingTuple>) = Load[#this] : &:r1554_4, ~m?
# 1554| mu1554_7(StructuredBindingTuple) = InitializeIndirection[#this] : &:r1554_6
# 1554| r1554_8(glval<double &>) = VariableAddress[#return] :
# 1554| r1554_9(glval<unknown>) = VariableAddress[#this] :
# 1554| r1554_10(StructuredBindingTuple *) = Load[#this] : &:r1554_9, ~m?
# 1554| r1554_11(glval<double>) = FieldAddress[d] : r1554_10
#-----| r0_1(double &) = CopyValue : r1554_11
#-----| mu0_2(double &) = Store[#return] : &:r1554_8, r0_1
# 1554| v1554_12(void) = ReturnIndirection[#this] : &:r1554_6, ~m?
# 1554| r1554_13(glval<double &>) = VariableAddress[#return] :
# 1554| v1554_14(void) = ReturnValue : &:r1554_13, ~m?
# 1554| v1554_15(void) = AliasedUse : ~m?
# 1554| v1554_16(void) = ExitFunction :
# 1556| std::tuple_element<int 2, StructuredBindingTuple>::type StructuredBindingTuple::get<int 2>()
# 1556| Block 0
# 1556| v1556_1(void) = EnterFunction :
# 1556| mu1556_2(unknown) = AliasedDefinition :
# 1556| mu1556_3(unknown) = InitializeNonLocal :
# 1556| r1556_4(glval<unknown>) = VariableAddress[#this] :
# 1556| mu1556_5(glval<StructuredBindingTuple>) = InitializeParameter[#this] : &:r1556_4
# 1556| r1556_6(glval<StructuredBindingTuple>) = Load[#this] : &:r1556_4, ~m?
# 1556| mu1556_7(StructuredBindingTuple) = InitializeIndirection[#this] : &:r1556_6
# 1556| r1556_8(glval<int &>) = VariableAddress[#return] :
# 1556| r1556_9(glval<unknown>) = VariableAddress[#this] :
# 1556| r1556_10(StructuredBindingTuple *) = Load[#this] : &:r1556_9, ~m?
# 1556| r1556_11(glval<int &>) = FieldAddress[r] : r1556_10
# 1556| r1556_12(int &) = Load[?] : &:r1556_11, ~m?
# 1556| r1556_13(glval<int>) = CopyValue : r1556_12
# 1556| r1556_14(int &) = CopyValue : r1556_13
# 1556| mu1556_15(int &) = Store[#return] : &:r1556_8, r1556_14
# 1556| v1556_16(void) = ReturnIndirection[#this] : &:r1556_6, ~m?
# 1556| r1556_17(glval<int &>) = VariableAddress[#return] :
# 1556| v1556_18(void) = ReturnValue : &:r1556_17, ~m?
# 1556| v1556_19(void) = AliasedUse : ~m?
# 1556| v1556_20(void) = ExitFunction :
# 1558| void tuple_structured_binding()
# 1558| Block 0
# 1558| v1558_1(void) = EnterFunction :
# 1558| mu1558_2(unknown) = AliasedDefinition :
# 1558| mu1558_3(unknown) = InitializeNonLocal :
# 1559| r1559_1(glval<StructuredBindingTuple>) = VariableAddress[t] :
# 1559| mu1559_2(StructuredBindingTuple) = Uninitialized[t] : &:r1559_1
# 1559| r1559_3(glval<unknown>) = FunctionAddress[StructuredBindingTuple] :
# 1559| v1559_4(void) = Call[StructuredBindingTuple] : func:r1559_3, this:r1559_1
# 1559| mu1559_5(unknown) = ^CallSideEffect : ~m?
# 1559| mu1559_6(StructuredBindingTuple) = ^IndirectMayWriteSideEffect[-1] : &:r1559_1
# 1562| r1562_1(glval<StructuredBindingTuple>) = VariableAddress[(unnamed local variable)] :
# 1562| r1562_2(glval<StructuredBindingTuple>) = VariableAddress[t] :
# 1562| r1562_3(StructuredBindingTuple) = Load[t] : &:r1562_2, ~m?
# 1562| mu1562_4(StructuredBindingTuple) = Store[(unnamed local variable)] : &:r1562_1, r1562_3
# 1562| r1562_5(glval<int &>) = VariableAddress[i] :
# 1562| r1562_6(glval<StructuredBindingTuple>) = VariableAddress[(unnamed local variable)] :
# 1562| r1562_7(glval<unknown>) = FunctionAddress[get] :
# 1562| r1562_8(int &) = Call[get] : func:r1562_7, this:r1562_6
# 1562| mu1562_9(unknown) = ^CallSideEffect : ~m?
# 1562| v1562_10(void) = ^IndirectReadSideEffect[-1] : &:r1562_6, ~m?
# 1562| mu1562_11(StructuredBindingTuple) = ^IndirectMayWriteSideEffect[-1] : &:r1562_6
# 1562| r1562_12(glval<int>) = CopyValue : r1562_8
# 1562| r1562_13(int &) = CopyValue : r1562_12
# 1562| mu1562_14(int &) = Store[i] : &:r1562_5, r1562_13
# 1562| r1562_15(glval<double &>) = VariableAddress[d] :
# 1562| r1562_16(glval<StructuredBindingTuple>) = VariableAddress[(unnamed local variable)] :
# 1562| r1562_17(glval<unknown>) = FunctionAddress[get] :
# 1562| r1562_18(double &) = Call[get] : func:r1562_17, this:r1562_16
# 1562| mu1562_19(unknown) = ^CallSideEffect : ~m?
# 1562| v1562_20(void) = ^IndirectReadSideEffect[-1] : &:r1562_16, ~m?
# 1562| mu1562_21(StructuredBindingTuple) = ^IndirectMayWriteSideEffect[-1] : &:r1562_16
# 1562| r1562_22(glval<double>) = CopyValue : r1562_18
# 1562| r1562_23(double &) = CopyValue : r1562_22
# 1562| mu1562_24(double &) = Store[d] : &:r1562_15, r1562_23
# 1562| r1562_25(glval<int &>) = VariableAddress[r] :
# 1562| r1562_26(glval<StructuredBindingTuple>) = VariableAddress[(unnamed local variable)] :
# 1562| r1562_27(glval<unknown>) = FunctionAddress[get] :
# 1562| r1562_28(int &) = Call[get] : func:r1562_27, this:r1562_26
# 1562| mu1562_29(unknown) = ^CallSideEffect : ~m?
# 1562| v1562_30(void) = ^IndirectReadSideEffect[-1] : &:r1562_26, ~m?
# 1562| mu1562_31(StructuredBindingTuple) = ^IndirectMayWriteSideEffect[-1] : &:r1562_26
# 1562| r1562_32(glval<int>) = CopyValue : r1562_28
# 1562| r1562_33(int &) = CopyValue : r1562_32
# 1562| mu1562_34(int &) = Store[r] : &:r1562_25, r1562_33
# 1563| r1563_1(double) = Constant[4.0] :
# 1563| r1563_2(glval<double &>) = VariableAddress[d] :
# 1563| r1563_3(double &) = Load[d] : &:r1563_2, ~m?
# 1563| r1563_4(glval<double>) = CopyValue : r1563_3
# 1563| mu1563_5(double) = Store[?] : &:r1563_4, r1563_1
# 1564| r1564_1(glval<double &>) = VariableAddress[rd] :
# 1564| r1564_2(glval<double &>) = VariableAddress[d] :
# 1564| r1564_3(double &) = Load[d] : &:r1564_2, ~m?
# 1564| r1564_4(glval<double>) = CopyValue : r1564_3
# 1564| r1564_5(double &) = CopyValue : r1564_4
# 1564| mu1564_6(double &) = Store[rd] : &:r1564_1, r1564_5
# 1565| r1565_1(glval<int>) = VariableAddress[v] :
# 1565| r1565_2(glval<int &>) = VariableAddress[i] :
# 1565| r1565_3(int &) = Load[i] : &:r1565_2, ~m?
# 1565| r1565_4(int) = Load[?] : &:r1565_3, ~m?
# 1565| mu1565_5(int) = Store[v] : &:r1565_1, r1565_4
# 1566| r1566_1(int) = Constant[5] :
# 1566| r1566_2(glval<int &>) = VariableAddress[r] :
# 1566| r1566_3(int &) = Load[r] : &:r1566_2, ~m?
# 1566| r1566_4(glval<int>) = CopyValue : r1566_3
# 1566| mu1566_5(int) = Store[?] : &:r1566_4, r1566_1
# 1567| r1567_1(glval<int &>) = VariableAddress[rr] :
# 1567| r1567_2(glval<int &>) = VariableAddress[r] :
# 1567| r1567_3(int &) = Load[r] : &:r1567_2, ~m?
# 1567| r1567_4(glval<int>) = CopyValue : r1567_3
# 1567| r1567_5(int &) = CopyValue : r1567_4
# 1567| mu1567_6(int &) = Store[rr] : &:r1567_1, r1567_5
# 1568| r1568_1(glval<int>) = VariableAddress[w] :
# 1568| r1568_2(glval<int &>) = VariableAddress[r] :
# 1568| r1568_3(int &) = Load[r] : &:r1568_2, ~m?
# 1568| r1568_4(int) = Load[?] : &:r1568_3, ~m?
# 1568| mu1568_5(int) = Store[w] : &:r1568_1, r1568_4
# 1572| r1572_1(glval<StructuredBindingTuple>) = VariableAddress[unnamed_local_variable] :
# 1572| r1572_2(glval<StructuredBindingTuple>) = VariableAddress[t] :
# 1572| r1572_3(StructuredBindingTuple) = Load[t] : &:r1572_2, ~m?
# 1572| mu1572_4(StructuredBindingTuple) = Store[unnamed_local_variable] : &:r1572_1, r1572_3
# 1573| r1573_1(glval<int &>) = VariableAddress[i] :
# 1573| r1573_2(glval<StructuredBindingTuple>) = VariableAddress[unnamed_local_variable] :
# 1573| r1573_3(glval<unknown>) = FunctionAddress[get] :
# 1573| r1573_4(int &) = Call[get] : func:r1573_3, this:r1573_2
# 1573| mu1573_5(unknown) = ^CallSideEffect : ~m?
# 1573| v1573_6(void) = ^IndirectReadSideEffect[-1] : &:r1573_2, ~m?
# 1573| mu1573_7(StructuredBindingTuple) = ^IndirectMayWriteSideEffect[-1] : &:r1573_2
# 1573| r1573_8(glval<int>) = CopyValue : r1573_4
# 1573| r1573_9(int &) = CopyValue : r1573_8
# 1573| mu1573_10(int &) = Store[i] : &:r1573_1, r1573_9
# 1574| r1574_1(glval<double &>) = VariableAddress[d] :
# 1574| r1574_2(glval<StructuredBindingTuple>) = VariableAddress[unnamed_local_variable] :
# 1574| r1574_3(glval<unknown>) = FunctionAddress[get] :
# 1574| r1574_4(double &) = Call[get] : func:r1574_3, this:r1574_2
# 1574| mu1574_5(unknown) = ^CallSideEffect : ~m?
# 1574| v1574_6(void) = ^IndirectReadSideEffect[-1] : &:r1574_2, ~m?
# 1574| mu1574_7(StructuredBindingTuple) = ^IndirectMayWriteSideEffect[-1] : &:r1574_2
# 1574| r1574_8(glval<double>) = CopyValue : r1574_4
# 1574| r1574_9(double &) = CopyValue : r1574_8
# 1574| mu1574_10(double &) = Store[d] : &:r1574_1, r1574_9
# 1575| r1575_1(glval<int &>) = VariableAddress[r] :
# 1575| r1575_2(glval<StructuredBindingTuple>) = VariableAddress[unnamed_local_variable] :
# 1575| r1575_3(glval<unknown>) = FunctionAddress[get] :
# 1575| r1575_4(int &) = Call[get] : func:r1575_3, this:r1575_2
# 1575| mu1575_5(unknown) = ^CallSideEffect : ~m?
# 1575| v1575_6(void) = ^IndirectReadSideEffect[-1] : &:r1575_2, ~m?
# 1575| mu1575_7(StructuredBindingTuple) = ^IndirectMayWriteSideEffect[-1] : &:r1575_2
# 1575| r1575_8(glval<int>) = CopyValue : r1575_4
# 1575| r1575_9(int &) = CopyValue : r1575_8
# 1575| mu1575_10(int &) = Store[r] : &:r1575_1, r1575_9
# 1576| r1576_1(double) = Constant[4.0] :
# 1576| r1576_2(glval<double &>) = VariableAddress[d] :
# 1576| r1576_3(double &) = Load[d] : &:r1576_2, ~m?
# 1576| r1576_4(glval<double>) = CopyValue : r1576_3
# 1576| mu1576_5(double) = Store[?] : &:r1576_4, r1576_1
# 1577| r1577_1(glval<double &>) = VariableAddress[rd] :
# 1577| r1577_2(glval<double &>) = VariableAddress[d] :
# 1577| r1577_3(double &) = Load[d] : &:r1577_2, ~m?
# 1577| r1577_4(glval<double>) = CopyValue : r1577_3
# 1577| r1577_5(double &) = CopyValue : r1577_4
# 1577| mu1577_6(double &) = Store[rd] : &:r1577_1, r1577_5
# 1578| r1578_1(glval<int>) = VariableAddress[v] :
# 1578| r1578_2(glval<int &>) = VariableAddress[i] :
# 1578| r1578_3(int &) = Load[i] : &:r1578_2, ~m?
# 1578| r1578_4(int) = Load[?] : &:r1578_3, ~m?
# 1578| mu1578_5(int) = Store[v] : &:r1578_1, r1578_4
# 1579| r1579_1(int) = Constant[5] :
# 1579| r1579_2(glval<int &>) = VariableAddress[r] :
# 1579| r1579_3(int &) = Load[r] : &:r1579_2, ~m?
# 1579| r1579_4(glval<int>) = CopyValue : r1579_3
# 1579| mu1579_5(int) = Store[?] : &:r1579_4, r1579_1
# 1580| r1580_1(glval<int &>) = VariableAddress[rr] :
# 1580| r1580_2(glval<int &>) = VariableAddress[r] :
# 1580| r1580_3(int &) = Load[r] : &:r1580_2, ~m?
# 1580| r1580_4(glval<int>) = CopyValue : r1580_3
# 1580| r1580_5(int &) = CopyValue : r1580_4
# 1580| mu1580_6(int &) = Store[rr] : &:r1580_1, r1580_5
# 1581| r1581_1(glval<int>) = VariableAddress[w] :
# 1581| r1581_2(glval<int &>) = VariableAddress[r] :
# 1581| r1581_3(int &) = Load[r] : &:r1581_2, ~m?
# 1581| r1581_4(int) = Load[?] : &:r1581_3, ~m?
# 1581| mu1581_5(int) = Store[w] : &:r1581_1, r1581_4
# 1583| v1583_1(void) = NoOp :
# 1558| v1558_4(void) = ReturnVoid :
# 1558| v1558_5(void) = AliasedUse : ~m?
# 1558| v1558_6(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -1,6 +1,6 @@
/**
* @name Uncontrolled data used in network request
* @description Sending network requests with user-controlled data allows for request forgery attacks.
* @name Server-side request forgery
* @description Making a network request with user-controlled data in the URL allows for request forgery attacks.
* @kind path-problem
* @problem.severity error
* @precision high

View File

@@ -0,0 +1,19 @@
@Controller
public class VelocitySSTI {
@GetMapping(value = "bad")
public void bad(HttpServletRequest request) {
Velocity.init();
String code = request.getParameter("code");
VelocityContext context = new VelocityContext();
context.put("name", "Velocity");
context.put("project", "Jakarta");
StringWriter w = new StringWriter();
// evaluate( Context context, Writer out, String logTag, String instring )
Velocity.evaluate(context, w, "mystring", code);
}
}

View File

@@ -0,0 +1,17 @@
@Controller
public class VelocitySSTI {
@GetMapping(value = "good")
public void good(HttpServletRequest request) {
Velocity.init();
VelocityContext context = new VelocityContext();
context.put("name", "Velocity");
context.put("project", "Jakarta");
String s = "We are using $project $name to render this.";
StringWriter w = new StringWriter();
Velocity.evaluate(context, w, "mystring", s);
System.out.println(" string : " + w);
}
}

View File

@@ -0,0 +1,31 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Template Injection occurs when user input is embedded in a template in an unsafe manner.
An attacker can use native template syntax to inject a malicious payload into a template, which is then executed server-side. This permits the attacker to run arbitrary code in the server's context.</p>
</overview>
<recommendation>
<p>
To fix this, ensure that an untrusted value is not used as a template. If the application requirements do not allow this, use a sandboxed environment where access to unsafe attributes and methods is prohibited.
</p>
</recommendation>
<example>
<p>
In the example given below, an untrusted HTTP parameter
<code>code</code>
is used as a Velocity template string. This can lead to remote code execution.
</p>
<sample src="SSTIBad.java" />
<p>
In the next example the problem is avoided by using a fixed template string
<code>s</code>
. Since, the template is not attacker controlled in this case, we prevent untrusted code execution.
</p>
<sample src="SSTIGood.java" />
</example>
<references>
<li>Portswigger : [Server Side Template Injection](https://portswigger.net/web-security/server-side-template-injection)</li>
</references>
</qhelp>

View File

@@ -0,0 +1,19 @@
/**
* @name Server Side Template Injection
* @description Untrusted input used as a template parameter can lead to remote code execution.
* @kind path-problem
* @problem.severity error
* @precision high
* @id java/server-side-template-injection
* @tags security
* external/cwe/cwe-094
*/
import java
import TemplateInjection
import DataFlow::PathGraph
from TemplateInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Potential arbitrary code execution due to $@.",
source.getNode(), "a template value loaded from a remote source."

View File

@@ -0,0 +1,209 @@
/** Definitions related to the Server Side Template Injection (SSTI) query. */
import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import experimental.semmle.code.java.frameworks.FreeMarker
import experimental.semmle.code.java.frameworks.Velocity
import experimental.semmle.code.java.frameworks.JinJava
import experimental.semmle.code.java.frameworks.Pebble
import experimental.semmle.code.java.frameworks.Thymeleaf
/** A taint tracking configuration to reason about Server Side Template Injection (SSTI) vulnerabilities */
class TemplateInjectionFlowConfig extends TaintTracking::Configuration {
TemplateInjectionFlowConfig() { this = "TemplateInjectionFlowConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
}
override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
exists(AdditionalFlowStep a | a.isAdditionalTaintStep(prev, succ))
}
}
/**
* A data flow sink for Server Side Template Injection (SSTI) vulnerabilities
*/
abstract private class Sink extends DataFlow::ExprNode { }
/**
* A data flow step for Server Side Template Injection (SSTI) vulnerabilities
*/
private class AdditionalFlowStep extends Unit {
abstract predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ);
}
/**
* An argument to FreeMarker template engine's `process` method call.
*/
private class FreeMarkerProcessSink extends Sink {
FreeMarkerProcessSink() {
exists(MethodAccess m |
m.getCallee() instanceof MethodFreeMarkerTemplateProcess and
m.getArgument(0) = this.getExpr()
)
}
}
/**
* An reader passed an argument to FreeMarker template engine's `Template`
* construtor call.
*/
private class FreeMarkerConstructorSink extends Sink {
FreeMarkerConstructorSink() {
// Template(java.lang.String name, java.io.Reader reader)
// Template(java.lang.String name, java.io.Reader reader, Configuration cfg)
// Template(java.lang.String name, java.io.Reader reader, Configuration cfg, java.lang.String encoding)
// Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg)
// Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg, ParserConfiguration customParserConfiguration, java.lang.String encoding)
// Template(java.lang.String name, java.lang.String sourceName, java.io.Reader reader, Configuration cfg, java.lang.String encoding)
exists(ConstructorCall cc, Expr e |
cc.getConstructor().getDeclaringType() instanceof TypeFreeMarkerTemplate and
e = cc.getAnArgument() and
(
e.getType().(RefType).hasQualifiedName("java.io", "Reader") and
this.asExpr() = e
)
)
or
exists(ConstructorCall cc |
cc.getConstructor().getDeclaringType() instanceof TypeFreeMarkerTemplate and
// Template(java.lang.String name, java.lang.String sourceCode, Configuration cfg)
cc.getNumArgument() = 3 and
cc.getArgument(1).getType() instanceof TypeString and
this.asExpr() = cc.getArgument(1)
)
}
}
/**
* An argument to FreeMarker template engine's `putTemplate` method call.
*/
private class FreeMarkerStringTemplateLoaderPutTemplateSink extends Sink {
FreeMarkerStringTemplateLoaderPutTemplateSink() {
exists(MethodAccess ma |
this.asExpr() = ma.getArgument(1) and
ma.getMethod() instanceof MethodFreeMarkerStringTemplateLoaderPutTemplate
)
}
}
/**
* An argument to Pebble template engine's `getLiteralTemplate` or `getTemplate` method call.
*/
private class PebbleGetTemplateSinkTemplateSink extends Sink {
PebbleGetTemplateSinkTemplateSink() {
exists(MethodAccess ma |
this.asExpr() = ma.getArgument(0) and
ma.getMethod() instanceof MethodPebbleGetTemplate
)
}
}
/**
* An argument to JinJava template engine's `render` or `renderForResult` method call.
*/
private class JinjavaRenderSink extends Sink {
JinjavaRenderSink() {
exists(MethodAccess ma |
this.asExpr() = ma.getArgument(0) and
(
ma.getMethod() instanceof MethodJinjavaRenderForResult
or
ma.getMethod() instanceof MethodJinjavaRender
)
)
}
}
/**
* An argument to ThymeLeaf template engine's `process` method call.
*/
private class ThymeLeafRenderSink extends Sink {
ThymeLeafRenderSink() {
exists(MethodAccess ma |
this.asExpr() = ma.getArgument(0) and
ma.getMethod() instanceof MethodThymeleafProcess
)
}
}
/**
* Tainted data flowing into a Velocity Context through `put` method taints the context.
*/
private class VelocityContextFlow extends AdditionalFlowStep {
override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
exists(MethodAccess m | m.getMethod() instanceof MethodVelocityContextPut |
m.getArgument(1) = prev.asExpr() and
succ.asExpr() = m.getQualifier()
)
}
}
/**
* An argument to Velocity template engine's `mergeTemplate` method call.
*/
private class VelocityMergeTempSink extends Sink {
VelocityMergeTempSink() {
exists(MethodAccess m |
// static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer)
m.getCallee() instanceof MethodVelocityMergeTemplate and
m.getArgument(2) = this.getExpr()
)
}
}
/**
* An argument to Velocity template engine's `mergeTemplate` method call.
*/
private class VelocityMergeSink extends Sink {
VelocityMergeSink() {
exists(MethodAccess m |
m.getCallee() instanceof MethodVelocityMerge and
// public void merge(Context context, Writer writer)
// public void merge(Context context, Writer writer, List<String> macroLibraries)
m.getArgument(0) = this.getExpr()
)
}
}
/**
* An argument to Velocity template engine's `evaluate` method call.
*/
private class VelocityEvaluateSink extends Sink {
VelocityEvaluateSink() {
exists(MethodAccess m |
m.getCallee() instanceof MethodVelocityEvaluate and
m.getArgument([0, 3]) = this.getExpr()
)
}
}
/**
* An argument to Velocity template engine's `parse` method call.
*/
private class VelocityParseSink extends Sink {
VelocityParseSink() {
exists(MethodAccess ma |
this.asExpr() = ma.getArgument(0) and
ma.getMethod() instanceof MethodVelocityParse
)
}
}
/**
* An argument to Velocity template engine's `putStringResource` method call.
*/
private class VelocityPutStringResSink extends Sink {
VelocityPutStringResSink() {
exists(MethodAccess ma |
this.asExpr() = ma.getArgument(1) and
ma.getMethod() instanceof MethodVelocityPutStringResource
)
}
}

View File

@@ -12,7 +12,7 @@
import java
import UnsafeUrlForward
import semmle.code.java.dataflow.FlowSources
import experimental.semmle.code.java.PathSanitizer
import DataFlow::PathGraph
class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
@@ -35,7 +35,7 @@ class UnsafeUrlForwardFlowConfig extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof UnsafeUrlForwardSanitizer }
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof UnsafeUrlForwardBarrierGuard
guard instanceof PathTraversalBarrierGuard
}
override DataFlow::FlowFeature getAFeature() {

View File

@@ -1,10 +1,5 @@
import java
import DataFlow
import semmle.code.java.controlflow.Guards
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.Servlets
import semmle.code.java.frameworks.spring.SpringWeb
import semmle.code.java.security.RequestForgery
private import semmle.code.java.dataflow.StringPrefixes
/** A sink for unsafe URL forward vulnerabilities. */
@@ -13,9 +8,6 @@ abstract class UnsafeUrlForwardSink extends DataFlow::Node { }
/** A sanitizer for unsafe URL forward vulnerabilities. */
abstract class UnsafeUrlForwardSanitizer extends DataFlow::Node { }
/** A barrier guard that protects against URL forward vulnerabilities. */
abstract class UnsafeUrlForwardBarrierGuard extends DataFlow::BarrierGuard { }
/** An argument to `getRequestDispatcher`. */
private class RequestDispatcherSink extends UnsafeUrlForwardSink {
RequestDispatcherSink() {
@@ -59,175 +51,6 @@ private class FollowsSanitizingPrefix extends UnsafeUrlForwardSanitizer {
FollowsSanitizingPrefix() { this.asExpr() = any(SanitizingPrefix fp).getAnAppendedExpression() }
}
/**
* A guard that considers safe a string being exactly compared to a trusted value.
*/
private class ExactStringPathMatchGuard extends UnsafeUrlForwardBarrierGuard instanceof MethodAccess {
ExactStringPathMatchGuard() {
super.getMethod().getDeclaringType() instanceof TypeString and
super.getMethod().getName() = ["equals", "equalsIgnoreCase"]
}
override predicate checks(Expr e, boolean branch) {
e = super.getQualifier() and
branch = true
}
}
private class AllowListGuard extends Guard instanceof MethodAccess {
AllowListGuard() {
(isStringPartialMatch(this) or isPathPartialMatch(this)) and
not isDisallowedWord(super.getAnArgument())
}
Expr getCheckedExpr() { result = super.getQualifier() }
}
/**
* A guard that considers a path safe because it is checked against an allowlist of partial trusted values.
* This requires additional protection against path traversal, either another guard (`PathTraversalGuard`)
* or a sanitizer (`PathNormalizeSanitizer`), to ensure any internal `..` components are removed from the path.
*/
private class AllowListBarrierGuard extends UnsafeUrlForwardBarrierGuard instanceof AllowListGuard {
override predicate checks(Expr e, boolean branch) {
e = super.getCheckedExpr() and
branch = true and
(
// Either a path normalization sanitizer comes before the guard,
exists(PathNormalizeSanitizer sanitizer | DataFlow::localExprFlow(sanitizer, e))
or
// or a check like `!path.contains("..")` comes before the guard
exists(PathTraversalGuard previousGuard |
DataFlow::localExprFlow(previousGuard.getCheckedExpr(), e) and
previousGuard.controls(this.getBasicBlock().(ConditionBlock), false)
)
)
}
}
/**
* A guard that considers a path safe because it is checked for `..` components, having previously
* been checked for a trusted prefix.
*/
private class DotDotCheckBarrierGuard extends UnsafeUrlForwardBarrierGuard instanceof PathTraversalGuard {
override predicate checks(Expr e, boolean branch) {
e = super.getCheckedExpr() and
branch = false and
// The same value has previously been checked against a list of allowed prefixes:
exists(AllowListGuard previousGuard |
DataFlow::localExprFlow(previousGuard.getCheckedExpr(), e) and
previousGuard.controls(this.getBasicBlock().(ConditionBlock), true)
)
}
}
private class BlockListGuard extends Guard instanceof MethodAccess {
BlockListGuard() {
(isStringPartialMatch(this) or isPathPartialMatch(this)) and
isDisallowedWord(super.getAnArgument())
}
Expr getCheckedExpr() { result = super.getQualifier() }
}
/**
* A guard that considers a string safe because it is checked against a blocklist of known dangerous values.
* This requires a prior check for URL encoding concealing a forbidden value, either a guard (`UrlEncodingGuard`)
* or a sanitizer (`UrlDecodeSanitizer`).
*/
private class BlockListBarrierGuard extends UnsafeUrlForwardBarrierGuard instanceof BlockListGuard {
override predicate checks(Expr e, boolean branch) {
e = super.getCheckedExpr() and
branch = false and
(
// Either `e` has been URL decoded:
exists(UrlDecodeSanitizer sanitizer | DataFlow::localExprFlow(sanitizer, e))
or
// or `e` has previously been checked for URL encoding sequences:
exists(UrlEncodingGuard previousGuard |
DataFlow::localExprFlow(previousGuard.getCheckedExpr(), e) and
previousGuard.controls(this.getBasicBlock(), false)
)
)
}
}
/**
* A guard that considers a string safe because it is checked for URL encoding sequences,
* having previously been checked against a block-list of forbidden values.
*/
private class URLEncodingBarrierGuard extends UnsafeUrlForwardBarrierGuard instanceof UrlEncodingGuard {
override predicate checks(Expr e, boolean branch) {
e = super.getCheckedExpr() and
branch = false and
exists(BlockListGuard previousGuard |
DataFlow::localExprFlow(previousGuard.getCheckedExpr(), e) and
previousGuard.controls(this.getBasicBlock(), false)
)
}
}
/**
* Holds if `ma` is a call to a method that checks a partial string match.
*/
private predicate isStringPartialMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypeString and
ma.getMethod().getName() =
["contains", "startsWith", "matches", "regionMatches", "indexOf", "lastIndexOf"]
}
/**
* Holds if `ma` is a call to a method of `java.nio.file.Path` that checks a partial path match.
*/
private predicate isPathPartialMatch(MethodAccess ma) {
ma.getMethod().getDeclaringType() instanceof TypePath and
ma.getMethod().getName() = "startsWith"
}
private predicate isDisallowedWord(CompileTimeConstantExpr word) {
word.getStringValue().matches(["%WEB-INF%", "%META-INF%", "%..%"])
}
/** A complementary guard that protects against path traversal, by looking for the literal `..`. */
private class PathTraversalGuard extends Guard instanceof MethodAccess {
Expr checked;
PathTraversalGuard() {
super.getMethod().getDeclaringType() instanceof TypeString and
super.getMethod().hasName(["contains", "indexOf"]) and
super.getAnArgument().(CompileTimeConstantExpr).getStringValue() = ".."
}
Expr getCheckedExpr() { result = super.getQualifier() }
}
/** A complementary sanitizer that protects against path traversal using path normalization. */
private class PathNormalizeSanitizer extends MethodAccess {
PathNormalizeSanitizer() {
this.getMethod().getDeclaringType().hasQualifiedName("java.nio.file", "Path") and
this.getMethod().hasName("normalize")
}
}
/** A complementary guard that protects against double URL encoding, by looking for the literal `%`. */
private class UrlEncodingGuard extends Guard instanceof MethodAccess {
UrlEncodingGuard() {
super.getMethod().getDeclaringType() instanceof TypeString and
super.getMethod().hasName(["contains", "indexOf"]) and
super.getAnArgument().(CompileTimeConstantExpr).getStringValue() = "%"
}
Expr getCheckedExpr() { result = super.getQualifier() }
}
/** A complementary sanitizer that protects against double URL encoding using URL decoding. */
private class UrlDecodeSanitizer extends MethodAccess {
UrlDecodeSanitizer() {
this.getMethod().getDeclaringType().hasQualifiedName("java.net", "URLDecoder") and
this.getMethod().hasName("decode")
}
}
private class ForwardPrefix extends InterestingPrefix {
ForwardPrefix() { this.getStringValue() = "forward:" }

View File

@@ -0,0 +1,29 @@
/** Definitions related to the FreeMarker Templating library. */
import java
/** The `Template` class of the FreeMarker Template Engine */
class TypeFreeMarkerTemplate extends Class {
TypeFreeMarkerTemplate() { this.hasQualifiedName("freemarker.template", "Template") }
}
/** The `process` method of the FreeMarker Template Engine's `Template` class */
class MethodFreeMarkerTemplateProcess extends Method {
MethodFreeMarkerTemplateProcess() {
this.getDeclaringType() instanceof TypeFreeMarkerTemplate and
this.hasName("process")
}
}
/** The `StringTemplateLoader` class of the FreeMarker Template Engine */
class TypeFreeMarkerStringLoader extends Class {
TypeFreeMarkerStringLoader() { this.hasQualifiedName("freemarker.cache", "StringTemplateLoader") }
}
/** The `process` method of the FreeMarker Template Engine's `StringTemplateLoader` class */
class MethodFreeMarkerStringTemplateLoaderPutTemplate extends Method {
MethodFreeMarkerStringTemplateLoaderPutTemplate() {
this.getDeclaringType() instanceof TypeFreeMarkerStringLoader and
this.hasName("putTemplate")
}
}

View File

@@ -0,0 +1,24 @@
/** Definitions related to the Jinjava Templating library. */
import java
/** The `Jinjava` class of the Jinjava Templating Engine. */
class TypeJinjava extends Class {
TypeJinjava() { this.hasQualifiedName("com.hubspot.jinjava", "Jinjava") }
}
/** The `render` method of the Jinjava Templating Engine. */
class MethodJinjavaRender extends Method {
MethodJinjavaRender() {
this.getDeclaringType() instanceof TypeJinjava and
this.hasName("render")
}
}
/** The `render` method of the Jinjava Templating Engine. */
class MethodJinjavaRenderForResult extends Method {
MethodJinjavaRenderForResult() {
this.getDeclaringType() instanceof TypeJinjava and
this.hasName("renderForResult")
}
}

View File

@@ -0,0 +1,16 @@
/** Definitions related to the Pebble Templating library. */
import java
/** The `PebbleEngine` class of the Pebble Templating Engine. */
class TypePebbleEngine extends Class {
TypePebbleEngine() { this.hasQualifiedName("com.mitchellbosecke.pebble", "PebbleEngine") }
}
/** The `getTemplate` method of the Pebble Templating Engine. */
class MethodPebbleGetTemplate extends Method {
MethodPebbleGetTemplate() {
this.getDeclaringType() instanceof TypePebbleEngine and
this.hasName(["getTemplate", "getLiteralTemplate"])
}
}

View File

@@ -0,0 +1,25 @@
/** Definitions related to the Thymeleaf Templating library. */
import java
/**
* A class implementing the `ITemplateEngine` interface of the Thymeleaf
* Templating Engine such as the `TemplateEngine` class.
*/
class TypeThymeleafTemplateEngine extends Class {
TypeThymeleafTemplateEngine() {
this.hasQualifiedName("org.thymeleaf", "TemplateEngine")
or
exists(Type t | this.getASupertype*().extendsOrImplements(t) |
t.hasName("org.thymeleaf.ITemplateEngine")
)
}
}
/** The `process` or `processThrottled` method of the Thymeleaf Templating Engine. */
class MethodThymeleafProcess extends Method {
MethodThymeleafProcess() {
this.getDeclaringType() instanceof TypeThymeleafTemplateEngine and
this.hasName(["process", "processThrottled"])
}
}

View File

@@ -0,0 +1,119 @@
/** Definitions related to the Apache Velocity Templating library. */
import java
/** The `org.apache.velocity.context.AbstractContext` class of the Velocity Templating Engine. */
class TypeVelocityAbstractContext extends Class {
TypeVelocityAbstractContext() {
this.hasQualifiedName("org.apache.velocity.context", "AbstractContext")
}
}
/** The `org.apache.velocity.runtime.RuntimeServices` class of the Velocity Templating Engine. */
class TypeVelocityRuntimeRuntimeServices extends Class {
TypeVelocityRuntimeRuntimeServices() {
this.hasQualifiedName("org.apache.velocity.runtime", "RuntimeServices")
}
}
/** The `org.apache.velocity.Template` class of the Velocity Templating Engine. */
class TypeVelocityTemplate extends Class {
TypeVelocityTemplate() { this.hasQualifiedName("org.apache.velocity", "Template") }
}
/** The `org.apache.velocity.runtime.RuntimeSingleton` classTemplating Engine. */
class TypeVelocityRuntimeRuntimeSingleton extends Class {
TypeVelocityRuntimeRuntimeSingleton() {
this.hasQualifiedName("org.apache.velocity.runtime", "RuntimeSingleton")
}
}
/** The `org.apache.velocity.VelocityEngine` class of the Velocity Templating Engine. */
class TypeVelocityVelocityEngine extends Class {
TypeVelocityVelocityEngine() { this.hasQualifiedName("org.apache.velocity", "VelocityEngine") }
}
/** The `org.apache.velocity.app.VelocityEngine` class of the Velocity Templating Engine. */
class TypeVelocityAppVelocityEngine extends RefType {
TypeVelocityAppVelocityEngine() {
this.hasQualifiedName("org.apache.velocity.app", "VelocityEngine")
}
}
/** The `org.apache.velocity.app.Velocity` class of the Velocity Templating Engine. */
class TypeVelocityAppVelocity extends RefType {
TypeVelocityAppVelocity() { this.hasQualifiedName("org.apache.velocity.app", "Velocity") }
}
/**
* The `org.apache.velocity.runtime.resource.util.StringResourceRepository` interface
* of the Velocity Templating Engine.
*/
class TypeVelocityStringResourceRepo extends RefType {
TypeVelocityStringResourceRepo() {
this.hasQualifiedName("org.apache.velocity.runtime.resource.util", "StringResourceRepository")
}
}
/** The `internalPut` and `put` methods of the Velocity Templating Engine. */
class MethodVelocityContextPut extends Method {
MethodVelocityContextPut() {
this.getDeclaringType().getASupertype*() instanceof TypeVelocityAbstractContext and
this.hasName(["put", "internalPut"])
}
}
/** The `evaluate` method of the Velocity Templating Engine. */
class MethodVelocityEvaluate extends Method {
MethodVelocityEvaluate() {
// static boolean evaluate(Context context, Writer out, String logTag, String instring)
// static boolean evaluate(Context context, Writer writer, String logTag, Reader reader)
(
this.getDeclaringType() instanceof TypeVelocityAppVelocity or
this.getDeclaringType() instanceof TypeVelocityAppVelocityEngine or
this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeServices
) and
this.hasName("evaluate")
}
}
/** The `mergeTemplate` method of the Velocity Templating Engine. */
class MethodVelocityMergeTemplate extends Method {
MethodVelocityMergeTemplate() {
// static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer)
(
this.getDeclaringType() instanceof TypeVelocityAppVelocity or
this.getDeclaringType() instanceof TypeVelocityAppVelocityEngine
) and
this.hasName("mergeTemplate")
}
}
/** The `merge` method of the Velocity Templating Engine. */
class MethodVelocityMerge extends Method {
MethodVelocityMerge() {
// void merge(Context context, Writer writer)
// void merge(Context context, Writer writer, List<String> macroLibraries)
this.getDeclaringType() instanceof TypeVelocityTemplate and
this.hasName("merge")
}
}
/** The `parse` method of the Velocity Templating Engine. */
class MethodVelocityParse extends Method {
MethodVelocityParse() {
(
this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeSingleton or
this.getDeclaringType().getASupertype*() instanceof TypeVelocityRuntimeRuntimeServices
) and
this.hasName("parse")
}
}
/** The `putStringResource` method of the Velocity Templating Engine. */
class MethodVelocityPutStringResource extends Method {
MethodVelocityPutStringResource() {
this.getDeclaringType().getASupertype*() instanceof TypeVelocityStringResourceRepo and
this.hasName("putStringResource")
}
}

View File

@@ -0,0 +1,132 @@
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.lang.String;
import java.io.Reader;
import java.io.StringReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import freemarker.template.Template;
import freemarker.template.Configuration;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.ParserConfiguration;
@Controller
public class FreemarkerSSTI {
String sourceName = "sourceName";
@GetMapping(value = "bad1")
public void bad1(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
Reader reader = new StringReader(code);
// Template(java.lang.String name, java.io.Reader reader)
Template t = new Template(name, reader);
}
@GetMapping(value = "bad2")
public void bad2(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
Reader reader = new StringReader(code);
Configuration cfg = new Configuration();
// Template(java.lang.String name, java.io.Reader reader, Configuration cfg)
Template t = new Template(name, reader, cfg);
}
@GetMapping(value = "bad3")
public void bad3(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
Reader reader = new StringReader(code);
Configuration cfg = new Configuration();
// Template(java.lang.String name, java.io.Reader reader, Configuration cfg,
// java.lang.String encoding)
Template t = new Template(name, reader, cfg, "UTF-8");
}
@GetMapping(value = "bad4")
public void bad4(HttpServletRequest request) {
String name = "ttemplate";
String sourceCode = request.getParameter("sourceCode");
Configuration cfg = new Configuration();
// Template(java.lang.String name, java.lang.String sourceCode, Configuration
// cfg)
Template t = new Template(name, sourceCode, cfg);
}
@GetMapping(value = "bad5")
public void bad5(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
Configuration cfg = new Configuration();
Reader reader = new StringReader(code);
// Template(java.lang.String name, java.lang.String sourceName, java.io.Reader
// reader, Configuration cfg)
Template t = new Template(name, sourceName, reader, cfg);
}
@GetMapping(value = "bad6")
public void bad6(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
Configuration cfg = new Configuration();
ParserConfiguration customParserConfiguration = new Configuration();
Reader reader = new StringReader(code);
// Template(java.lang.String name, java.lang.String sourceName, java.io.Reader
// reader, Configuration cfg, ParserConfiguration customParserConfiguration,
// java.lang.String encoding)
Template t = new Template(name, sourceName, reader, cfg, customParserConfiguration, "UTF-8");
}
@GetMapping(value = "bad7")
public void bad7(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
Configuration cfg = new Configuration();
ParserConfiguration customParserConfiguration = new Configuration();
Reader reader = new StringReader(code);
// Template(java.lang.String name, java.lang.String sourceName, java.io.Reader
// reader, Configuration cfg, java.lang.String encoding)
Template t = new Template(name, sourceName, reader, cfg, "UTF-8");
}
@GetMapping(value = "bad8")
public void bad8(HttpServletRequest request) {
String code = request.getParameter("code");
StringTemplateLoader stringLoader = new StringTemplateLoader();
// void putTemplate(java.lang.String name, java.lang.String templateContent)
stringLoader.putTemplate("myTemplate", code);
}
@GetMapping(value = "bad9")
public void bad9(HttpServletRequest request) {
String code = request.getParameter("code");
StringTemplateLoader stringLoader = new StringTemplateLoader();
// void putTemplate(java.lang.String name, java.lang.String templateContent,
// long lastModified)
stringLoader.putTemplate("myTemplate", code, 0);
}
@GetMapping(value = "bad10")
public void bad10(HttpServletRequest request) {
HashMap root = new HashMap();
String code = request.getParameter("code");
root.put("code", code);
Configuration cfg = new Configuration();
Template temp = cfg.getTemplate("test.ftlh");
OutputStreamWriter out = new OutputStreamWriter(System.out);
temp.process(root, out);
}
}

View File

@@ -0,0 +1,48 @@
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.lang.String;
import java.io.Reader;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import com.hubspot.jinjava.*;
import com.hubspot.jinjava.JinjavaConfig;
import com.hubspot.jinjava.interpret.*;
@Controller
public class JinJavaSSTI {
String sourceName = "sourceName";
@GetMapping(value = "bad1")
public void bad1(HttpServletRequest request) {
String template = request.getParameter("template");
Jinjava jinjava = new Jinjava();
Map<String, Object> context = new HashMap<>();
// String render(String template, Map<String, ?> bindings)
String renderedTemplate = jinjava.render(template, context);
}
@GetMapping(value = "bad2")
public void bad2(HttpServletRequest request) {
String template = request.getParameter("template");
Jinjava jinjava = new Jinjava();
Map<String, Object> bindings = new HashMap<>();
// RenderResult renderForResult (String template, Map<String, ?> bindings)
RenderResult renderResult = jinjava.renderForResult(template, bindings);
}
@GetMapping(value = "bad3")
public void bad3(HttpServletRequest request) {
String template = request.getParameter("template");
Jinjava jinjava = new Jinjava();
Map<String, Object> bindings = new HashMap<>();
JinjavaConfig renderConfig = new JinjavaConfig();
// RenderResult renderForResult (String template, Map<String, ?> bindings,
// JinjavaConfig renderConfig)
RenderResult renderResult = jinjava.renderForResult(template, bindings, renderConfig);
}
}

View File

@@ -0,0 +1,30 @@
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.lang.String;
import java.io.Reader;
import java.io.StringReader;
import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.template.*;
@Controller
public class PebbleSSTI {
String sourceName = "sourceName";
@GetMapping(value = "bad1")
public void bad1(HttpServletRequest request) {
String code = request.getParameter("code");
PebbleEngine engine = new PebbleEngine.Builder().build();
// public PebbleTemplate getTemplate(String templateName)
PebbleTemplate compiledTemplate = engine.getTemplate(code);
}
@GetMapping(value = "bad2")
public void bad2(HttpServletRequest request) {
String code = request.getParameter("code");
PebbleEngine engine = new PebbleEngine.Builder().build();
// public PebbleTemplate getLiteralTemplate(String templateName)
PebbleTemplate compiledTemplate = engine.getLiteralTemplate(code);
}
}

View File

@@ -0,0 +1,136 @@
edges
| FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | FreemarkerSSTI.java:24:36:24:39 | code : String |
| FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:27:35:27:40 | reader |
| FreemarkerSSTI.java:24:36:24:39 | code : String | FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | FreemarkerSSTI.java:34:36:34:39 | code : String |
| FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:38:35:38:40 | reader |
| FreemarkerSSTI.java:34:36:34:39 | code : String | FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | FreemarkerSSTI.java:45:36:45:39 | code : String |
| FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:50:35:50:40 | reader |
| FreemarkerSSTI.java:45:36:45:39 | code : String | FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | FreemarkerSSTI.java:61:35:61:44 | sourceCode |
| FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | FreemarkerSSTI.java:69:36:69:39 | code : String |
| FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:73:47:73:52 | reader |
| FreemarkerSSTI.java:69:36:69:39 | code : String | FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | FreemarkerSSTI.java:82:36:82:39 | code : String |
| FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:87:47:87:52 | reader |
| FreemarkerSSTI.java:82:36:82:39 | code : String | FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | FreemarkerSSTI.java:96:36:96:39 | code : String |
| FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader | FreemarkerSSTI.java:100:47:100:52 | reader |
| FreemarkerSSTI.java:96:36:96:39 | code : String | FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | FreemarkerSSTI.java:109:42:109:45 | code |
| FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | FreemarkerSSTI.java:119:42:119:45 | code |
| FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | FreemarkerSSTI.java:126:26:126:29 | code : String |
| FreemarkerSSTI.java:126:9:126:12 | root [post update] [<map.value>] : String | FreemarkerSSTI.java:130:22:130:25 | root |
| FreemarkerSSTI.java:126:26:126:29 | code : String | FreemarkerSSTI.java:126:9:126:12 | root [post update] [<map.value>] : String |
| JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | JinJavaSSTI.java:25:44:25:51 | template |
| JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | JinJavaSSTI.java:34:55:34:62 | template |
| JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | JinJavaSSTI.java:46:55:46:62 | template |
| PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | PebbleSSTI.java:21:56:21:59 | code |
| PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | PebbleSSTI.java:28:63:28:66 | code |
| ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | ThymeleafSSTI.java:27:27:27:30 | code |
| VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | VelocitySSTI.java:38:45:38:48 | code |
| VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | VelocitySSTI.java:50:42:50:45 | code : String |
| VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader | VelocitySSTI.java:53:45:53:50 | reader |
| VelocitySSTI.java:50:42:50:45 | code : String | VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader |
| VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | VelocitySSTI.java:62:42:62:45 | code : String |
| VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader | VelocitySSTI.java:63:25:63:30 | reader |
| VelocitySSTI.java:62:42:62:45 | code : String | VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader |
| VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | VelocitySSTI.java:77:21:77:27 | context |
| VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | VelocitySSTI.java:89:60:89:66 | context |
| VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | VelocitySSTI.java:102:11:102:17 | context |
| VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | VelocitySSTI.java:115:11:115:17 | context |
| VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | VelocitySSTI.java:123:37:123:40 | code |
nodes
| FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:24:19:24:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:24:36:24:39 | code : String | semmle.label | code : String |
| FreemarkerSSTI.java:27:35:27:40 | reader | semmle.label | reader |
| FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:34:19:34:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:34:36:34:39 | code : String | semmle.label | code : String |
| FreemarkerSSTI.java:38:35:38:40 | reader | semmle.label | reader |
| FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:45:19:45:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:45:36:45:39 | code : String | semmle.label | code : String |
| FreemarkerSSTI.java:50:35:50:40 | reader | semmle.label | reader |
| FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:61:35:61:44 | sourceCode | semmle.label | sourceCode |
| FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:69:19:69:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:69:36:69:39 | code : String | semmle.label | code : String |
| FreemarkerSSTI.java:73:47:73:52 | reader | semmle.label | reader |
| FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:82:19:82:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:82:36:82:39 | code : String | semmle.label | code : String |
| FreemarkerSSTI.java:87:47:87:52 | reader | semmle.label | reader |
| FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:96:19:96:40 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
| FreemarkerSSTI.java:96:36:96:39 | code : String | semmle.label | code : String |
| FreemarkerSSTI.java:100:47:100:52 | reader | semmle.label | reader |
| FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:109:42:109:45 | code | semmle.label | code |
| FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:119:42:119:45 | code | semmle.label | code |
| FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| FreemarkerSSTI.java:126:9:126:12 | root [post update] [<map.value>] : String | semmle.label | root [post update] [<map.value>] : String |
| FreemarkerSSTI.java:126:26:126:29 | code : String | semmle.label | code : String |
| FreemarkerSSTI.java:130:22:130:25 | root | semmle.label | root |
| JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JinJavaSSTI.java:25:44:25:51 | template | semmle.label | template |
| JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JinJavaSSTI.java:34:55:34:62 | template | semmle.label | template |
| JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| JinJavaSSTI.java:46:55:46:62 | template | semmle.label | template |
| PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| PebbleSSTI.java:21:56:21:59 | code | semmle.label | code |
| PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| PebbleSSTI.java:28:63:28:66 | code | semmle.label | code |
| ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| ThymeleafSSTI.java:27:27:27:30 | code | semmle.label | code |
| VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| VelocitySSTI.java:38:45:38:48 | code | semmle.label | code |
| VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| VelocitySSTI.java:50:25:50:46 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
| VelocitySSTI.java:50:42:50:45 | code : String | semmle.label | code : String |
| VelocitySSTI.java:53:45:53:50 | reader | semmle.label | reader |
| VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| VelocitySSTI.java:62:25:62:46 | new StringReader(...) : StringReader | semmle.label | new StringReader(...) : StringReader |
| VelocitySSTI.java:62:42:62:45 | code : String | semmle.label | code : String |
| VelocitySSTI.java:63:25:63:30 | reader | semmle.label | reader |
| VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| VelocitySSTI.java:77:21:77:27 | context | semmle.label | context |
| VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| VelocitySSTI.java:89:60:89:66 | context | semmle.label | context |
| VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| VelocitySSTI.java:102:11:102:17 | context | semmle.label | context |
| VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| VelocitySSTI.java:115:11:115:17 | context | semmle.label | context |
| VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| VelocitySSTI.java:123:37:123:40 | code | semmle.label | code |
subpaths
#select
| FreemarkerSSTI.java:27:35:27:40 | reader | FreemarkerSSTI.java:23:17:23:44 | getParameter(...) : String | FreemarkerSSTI.java:27:35:27:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:23:17:23:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:38:35:38:40 | reader | FreemarkerSSTI.java:33:17:33:44 | getParameter(...) : String | FreemarkerSSTI.java:38:35:38:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:33:17:33:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:50:35:50:40 | reader | FreemarkerSSTI.java:44:17:44:44 | getParameter(...) : String | FreemarkerSSTI.java:50:35:50:40 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:44:17:44:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:61:35:61:44 | sourceCode | FreemarkerSSTI.java:56:23:56:56 | getParameter(...) : String | FreemarkerSSTI.java:61:35:61:44 | sourceCode | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:56:23:56:56 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:73:47:73:52 | reader | FreemarkerSSTI.java:67:17:67:44 | getParameter(...) : String | FreemarkerSSTI.java:73:47:73:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:67:17:67:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:87:47:87:52 | reader | FreemarkerSSTI.java:79:17:79:44 | getParameter(...) : String | FreemarkerSSTI.java:87:47:87:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:79:17:79:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:100:47:100:52 | reader | FreemarkerSSTI.java:93:17:93:44 | getParameter(...) : String | FreemarkerSSTI.java:100:47:100:52 | reader | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:93:17:93:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:109:42:109:45 | code | FreemarkerSSTI.java:105:17:105:44 | getParameter(...) : String | FreemarkerSSTI.java:109:42:109:45 | code | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:105:17:105:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:119:42:119:45 | code | FreemarkerSSTI.java:114:17:114:44 | getParameter(...) : String | FreemarkerSSTI.java:119:42:119:45 | code | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:114:17:114:44 | getParameter(...) | a template value loaded from a remote source. |
| FreemarkerSSTI.java:130:22:130:25 | root | FreemarkerSSTI.java:125:17:125:44 | getParameter(...) : String | FreemarkerSSTI.java:130:22:130:25 | root | Potential arbitrary code execution due to $@. | FreemarkerSSTI.java:125:17:125:44 | getParameter(...) | a template value loaded from a remote source. |
| JinJavaSSTI.java:25:44:25:51 | template | JinJavaSSTI.java:21:21:21:52 | getParameter(...) : String | JinJavaSSTI.java:25:44:25:51 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:21:21:21:52 | getParameter(...) | a template value loaded from a remote source. |
| JinJavaSSTI.java:34:55:34:62 | template | JinJavaSSTI.java:30:21:30:52 | getParameter(...) : String | JinJavaSSTI.java:34:55:34:62 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:30:21:30:52 | getParameter(...) | a template value loaded from a remote source. |
| JinJavaSSTI.java:46:55:46:62 | template | JinJavaSSTI.java:39:21:39:52 | getParameter(...) : String | JinJavaSSTI.java:46:55:46:62 | template | Potential arbitrary code execution due to $@. | JinJavaSSTI.java:39:21:39:52 | getParameter(...) | a template value loaded from a remote source. |
| PebbleSSTI.java:21:56:21:59 | code | PebbleSSTI.java:18:17:18:44 | getParameter(...) : String | PebbleSSTI.java:21:56:21:59 | code | Potential arbitrary code execution due to $@. | PebbleSSTI.java:18:17:18:44 | getParameter(...) | a template value loaded from a remote source. |
| PebbleSSTI.java:28:63:28:66 | code | PebbleSSTI.java:25:17:25:44 | getParameter(...) : String | PebbleSSTI.java:28:63:28:66 | code | Potential arbitrary code execution due to $@. | PebbleSSTI.java:25:17:25:44 | getParameter(...) | a template value loaded from a remote source. |
| ThymeleafSSTI.java:27:27:27:30 | code | ThymeleafSSTI.java:22:17:22:44 | getParameter(...) : String | ThymeleafSSTI.java:27:27:27:30 | code | Potential arbitrary code execution due to $@. | ThymeleafSSTI.java:22:17:22:44 | getParameter(...) | a template value loaded from a remote source. |
| VelocitySSTI.java:38:45:38:48 | code | VelocitySSTI.java:31:17:31:44 | getParameter(...) : String | VelocitySSTI.java:38:45:38:48 | code | Potential arbitrary code execution due to $@. | VelocitySSTI.java:31:17:31:44 | getParameter(...) | a template value loaded from a remote source. |
| VelocitySSTI.java:53:45:53:50 | reader | VelocitySSTI.java:44:17:44:44 | getParameter(...) : String | VelocitySSTI.java:53:45:53:50 | reader | Potential arbitrary code execution due to $@. | VelocitySSTI.java:44:17:44:44 | getParameter(...) | a template value loaded from a remote source. |
| VelocitySSTI.java:63:25:63:30 | reader | VelocitySSTI.java:59:17:59:44 | getParameter(...) : String | VelocitySSTI.java:63:25:63:30 | reader | Potential arbitrary code execution due to $@. | VelocitySSTI.java:59:17:59:44 | getParameter(...) | a template value loaded from a remote source. |
| VelocitySSTI.java:77:21:77:27 | context | VelocitySSTI.java:69:17:69:44 | getParameter(...) : String | VelocitySSTI.java:77:21:77:27 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:69:17:69:44 | getParameter(...) | a template value loaded from a remote source. |
| VelocitySSTI.java:89:60:89:66 | context | VelocitySSTI.java:83:17:83:44 | getParameter(...) : String | VelocitySSTI.java:89:60:89:66 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:83:17:83:44 | getParameter(...) | a template value loaded from a remote source. |
| VelocitySSTI.java:102:11:102:17 | context | VelocitySSTI.java:95:17:95:44 | getParameter(...) : String | VelocitySSTI.java:102:11:102:17 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:95:17:95:44 | getParameter(...) | a template value loaded from a remote source. |
| VelocitySSTI.java:115:11:115:17 | context | VelocitySSTI.java:108:17:108:44 | getParameter(...) : String | VelocitySSTI.java:115:11:115:17 | context | Potential arbitrary code execution due to $@. | VelocitySSTI.java:108:17:108:44 | getParameter(...) | a template value loaded from a remote source. |
| VelocitySSTI.java:123:37:123:40 | code | VelocitySSTI.java:120:17:120:44 | getParameter(...) : String | VelocitySSTI.java:123:37:123:40 | code | Potential arbitrary code execution due to $@. | VelocitySSTI.java:120:17:120:44 | getParameter(...) | a template value loaded from a remote source. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-094/TemplateInjection.ql

View File

@@ -0,0 +1,31 @@
import javax.imageio.stream.FileImageInputStream;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.lang.String;
import java.io.File;
import java.io.FileWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import org.thymeleaf.*;
import org.thymeleaf.context.Context;
@Controller
public class ThymeleafSSTI {
String sourceName = "sourceName";
@GetMapping(value = "bad1")
public void bad1(HttpServletRequest request) {
String code = request.getParameter("code");
Context ctx = new Context();
try {
FileWriter fw = new FileWriter(new File("as"));
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.process(code, ctx, fw);
} catch (Exception e) {
}
}
}

View File

@@ -0,0 +1,126 @@
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.lang.String;
import java.io.Reader;
import java.io.StringReader;
import java.io.OutputStreamWriter;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.LinkedList;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.context.AbstractContext;
import org.apache.velocity.context.Context;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.resource.util.StringResourceRepository;
import org.apache.velocity.runtime.resource.util.StringResourceRepositoryImpl;
@Controller
public class VelocitySSTI {
String sourceName = "sourceName";
@GetMapping(value = "bad1")
public void bad1(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
VelocityContext context = null;
String s = "We are using $project $name to render this.";
StringWriter w = new StringWriter();
// evaluate( Context context, Writer out, String logTag, String instring )
Velocity.evaluate(context, w, "mystring", code);
}
@GetMapping(value = "bad2")
public void bad2(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
VelocityContext context = null;
String s = "We are using $project $name to render this.";
StringWriter w = new StringWriter();
StringReader reader = new StringReader(code);
// evaluate(Context context, Writer writer, String logTag, Reader reader)
Velocity.evaluate(context, w, "mystring", reader);
}
@GetMapping(value = "bad3")
public void bad3(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
RuntimeServices runtimeServices = new RuntimeServices();
StringReader reader = new StringReader(code);
runtimeServices.parse(reader, new Template());
}
@GetMapping(value = "bad4")
public void bad4(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
VelocityContext context = new VelocityContext();
context.put("code", code);
StringWriter w = new StringWriter();
StringReader reader = new StringReader("test");
Velocity.evaluate(context, w, "mystring", reader);
}
@GetMapping(value = "bad5")
public void bad5(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
VelocityContext context = new VelocityContext();
context.put("code", code);
StringWriter w = new StringWriter();
VelocityEngine.mergeTemplate("testtemplate.vm", "UTF-8", context, w);
}
@GetMapping(value = "bad6")
public void bad6(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
VelocityContext context = new VelocityContext();
context.put("code", code);
StringWriter w = new StringWriter();
Template t = new Template();
t.merge(context, w);
}
@GetMapping(value = "bad7")
public void bad7(HttpServletRequest request) {
String name = "ttemplate";
String code = request.getParameter("code");
VelocityContext context = new VelocityContext();
context.put("code", code);
StringWriter w = new StringWriter();
Template t = new Template();
t.merge(context, w, new LinkedList<String>());
}
@GetMapping(value = "bad8")
public void bad8(HttpServletRequest request) {
String code = request.getParameter("code");
StringResourceRepository repo = new StringResourceRepositoryImpl();
repo.putStringResource("woogie2", code);
}
}

View File

@@ -1 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2:${testdir}/../../../../experimental/stubs/rhino-1.7.13:${testdir}/../../../../stubs/bsh-2.0b5:${testdir}/../../../../experimental/stubs/jshell
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8:${testdir}/../../../../stubs/jsr223-api:${testdir}/../../../../stubs/scriptengine:${testdir}/../../../../stubs/java-ee-el:${testdir}/../../../../stubs/juel-2.2:${testdir}/../../../../stubs/servlet-api-2.4:${testdir}/../../../../stubs/jython-2.7.2:${testdir}/../../../../experimental/stubs/rhino-1.7.13:${testdir}/../../../../stubs/bsh-2.0b5:${testdir}/../../../../experimental/stubs/jshell:${testdir}/../../../../experimental/stubs/apache-freemarker-2.3.31:${testdir}/../../../../experimental/stubs/jinjava-2.6.0:${testdir}/../../../../experimental/stubs/pebble-3.1.5:${testdir}/../../../../experimental/stubs/thymeleaf-3.0.14:${testdir}/../../../../experimental/stubs/apache-velocity-2.3

View File

@@ -0,0 +1,7 @@
package freemarker.cache;
public class StringTemplateLoader {
public StringTemplateLoader() {}
public void putTemplate(java.lang.String name, java.lang.String templateContent){}
public void putTemplate(java.lang.String name, java.lang.String templateContent, long lastModified){}
}

View File

@@ -0,0 +1,9 @@
package freemarker.template;
import freemarker.template.Template;
public class Configuration implements ParserConfiguration {
public Configuration() {}
public Template getTemplate(java.lang.String name){return null;}
}

View File

@@ -0,0 +1,3 @@
package freemarker.template;
public interface ObjectWrapper {}

View File

@@ -0,0 +1,3 @@
package freemarker.template;
public interface ParserConfiguration {}

View File

@@ -0,0 +1,55 @@
package freemarker.template;
import java.io.Reader;
import java.lang.String;
public class Template {
public Template(String name, Reader reader) {
}
public Template(String name, Reader reader, Configuration cfg) {
}
public Template(String name, Reader reader, Configuration cfg, String encoding) {
}
public Template(String name, String sourceCode, Configuration cfg) {
}
public Template(String name, String sourceName, Reader reader, Configuration cfg) {
}
public Template(
String name,
String sourceName,
Reader reader,
Configuration cfg,
ParserConfiguration customParserConfiguration,
String encoding) {
}
public Template(
String name,
String sourceName,
Reader reader,
Configuration cfg,
String encoding) {
}
public void process(java.lang.Object dataModel, java.io.Writer out) {
}
public void process(
java.lang.Object dataModel,
java.io.Writer out,
ObjectWrapper wrapper) {
}
public void process(
java.lang.Object dataModel,
java.io.Writer out,
ObjectWrapper wrapper,
TemplateNodeModel rootNode) {
}
}

View File

@@ -0,0 +1,3 @@
package freemarker.template;
public interface TemplateNodeModel {}

View File

@@ -0,0 +1,13 @@
package org.apache.velocity;
import org.apache.velocity.context.Context;
import java.io.Writer;
import java.util.List;
public class Template {
public void merge(Context context, Writer writer) {
}
public void merge(Context context, Writer writer, List<String> macroLibraries) {
}
}

View File

@@ -0,0 +1,10 @@
package org.apache.velocity;
import org.apache.velocity.context.AbstractContext;
import org.apache.velocity.context.Context;
import java.io.Writer;
public class VelocityContext extends AbstractContext implements Context {
public VelocityContext() {
}
}

View File

@@ -0,0 +1,20 @@
package org.apache.velocity;
import org.apache.velocity.context;
import java.io.Writer;
import java.lang.String;
import java.io.Reader;
public class VelocityEngine {
public static boolean evaluate(Context context, Writer out, String logTag, String instring) {
return true;
}
public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) {
return true;
}
public static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer) {
return true;
}
}

View File

@@ -0,0 +1,15 @@
package org.apache.velocity.app;
import org.apache.velocity.context.Context;
import java.io.Reader;
import java.io.Writer;
public class Velocity {
public static boolean evaluate(Context context, Writer out, String logTag, String instring) {
return true;
}
public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) {
return true;
}
}

View File

@@ -0,0 +1,20 @@
package org.apache.velocity.app;
import org.apache.velocity.context.Context;
import java.io.Writer;
import java.lang.String;
import java.io.Reader;
public class VelocityEngine {
public static boolean evaluate(Context context, Writer out, String logTag, String instring) {
return true;
}
public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) {
return true;
}
public static boolean mergeTemplate(String templateName, String encoding, Context context, Writer writer) {
return true;
}
}

View File

@@ -0,0 +1,14 @@
package org.apache.velocity.context;
import org.apache.velocity.context.Context;
import java.io.Writer;
public class AbstractContext implements Context {
public Object put(String key, Object value) {
return null;
}
public Object internalPut(String key, Object value) {
return null;
}
}

View File

@@ -0,0 +1,7 @@
package org.apache.velocity.context;
public interface Context {
public Object put(String key, Object value);
public Object internalPut(String key, Object value);
}

View File

@@ -0,0 +1,25 @@
package org.apache.velocity.runtime;
import org.apache.velocity.runtime.parser.node.*;
import org.apache.velocity.context.Context;
import java.io.Reader;
import java.io.Writer;
import org.apache.velocity.Template;
public class RuntimeServices {
public RuntimeServices() {
}
public static SimpleNode parse(Reader reader, Template template) {
return null;
}
public static boolean evaluate(Context context, Writer out, String logTag, String instring) {
return true;
}
public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) {
return true;
}
}

View File

@@ -0,0 +1,8 @@
package org.apache.velocity.runtime;
import org.apache.velocity.runtime.parser.node.*;
public class RuntimeSingleton {
public static SimpleNode parse(Reader reader, Template template) {
}
}

View File

@@ -0,0 +1,5 @@
package org.apache.velocity.runtime.parser.node;
public class SimpleNode {
}

View File

@@ -0,0 +1,7 @@
package org.apache.velocity.runtime.resource.util;
public interface StringResourceRepository {
public void putStringResource(String name, String body);
public void putStringResource(String name, String body, String encoding);
}

View File

@@ -0,0 +1,9 @@
package org.apache.velocity.runtime.resource.util;
public class StringResourceRepositoryImpl implements StringResourceRepository {
public void putStringResource(String name, String body) {
}
public void putStringResource(String name, String body, String encoding) {
}
}

View File

@@ -0,0 +1,24 @@
package com.hubspot.jinjava;
import com.hubspot.jinjava.JinjavaConfig;
import com.hubspot.jinjava.interpret.RenderResult;
import java.lang.String;
import java.util.Map;
public class Jinjava {
public Jinjava() {
}
public String render(String template, Map<String, ?> bindings) {
return "test";
};
public RenderResult renderForResult(String template, Map<String, ?> bindings) {
return new RenderResult("result");
}
public RenderResult renderForResult(String template, Map<String, ?> bindings, JinjavaConfig renderConfig) {
return new RenderResult("result");
}
}

View File

@@ -0,0 +1,5 @@
package com.hubspot.jinjava;
public class JinjavaConfig {
}

View File

@@ -0,0 +1,6 @@
package com.hubspot.jinjava.interpret;
public class RenderResult {
public RenderResult(String result) {
}
}

View File

@@ -0,0 +1,27 @@
package com.mitchellbosecke.pebble;
import com.mitchellbosecke.pebble.template.*;
public class PebbleEngine {
public static class Builder {
public Builder() {
};
public PebbleEngine build() {
return new PebbleEngine();
}
};
PebbleEngine() {
}
public PebbleTemplate getLiteralTemplate(String templateName) {
return new PebbleTemplate() {
};
}
public PebbleTemplate getTemplate(String templateName) {
return new PebbleTemplate() {
};
}
}

View File

@@ -0,0 +1,3 @@
package com.mitchellbosecke.pebble.template;
public interface PebbleTemplate {}

View File

@@ -0,0 +1,28 @@
package org.thymeleaf;
import java.io.Writer;
import java.lang.String;
import java.util.Set;
import org.thymeleaf.context.IContext;
import org.thymeleaf.*;
public interface ITemplateEngine {
public String process(String template, Set<String> templateSelectors, IContext context);
public void process(String template, Set<String> templateSelectors, IContext context, Writer writer);
public String process(String template, IContext context);
public void process(String template, IContext context, Writer writer);
public String process(TemplateSpec templateSpec, IContext context);
public void process(TemplateSpec templateSpec, IContext context, Writer writer);
public IThrottledTemplateProcessor processThrottled(String template, Set<String> templateSelectors, IContext context);
public IThrottledTemplateProcessor processThrottled(String template, IContext context);
public IThrottledTemplateProcessor processThrottled(TemplateSpec templateSpec, IContext context);
}

View File

@@ -0,0 +1,5 @@
package org.thymeleaf;
public interface IThrottledTemplateProcessor {
}

View File

@@ -0,0 +1,51 @@
package org.thymeleaf;
import java.io.Writer;
import java.lang.String;
import java.util.Set;
import org.thymeleaf.context.IContext;
import org.thymeleaf.TemplateSpec;
import org.thymeleaf.ITemplateEngine;
import org.thymeleaf.IThrottledTemplateProcessor;
public class TemplateEngine implements ITemplateEngine {
public String process(String template, Set<String> templateSelectors, IContext context) {
return "";
}
public void process(String template, Set<String> templateSelectors, IContext context, Writer writer) {
}
public String process(String template, IContext context) {
return "";
}
public void process(String template, IContext context, Writer writer) {
}
public String process(TemplateSpec templateSpec, IContext context) {
return "";
}
public void process(TemplateSpec templateSpec, IContext context, Writer writer) {
}
public IThrottledTemplateProcessor processThrottled(String template, Set<String> templateSelectors,
IContext context) {
return new IThrottledTemplateProcessor() {
};
}
public IThrottledTemplateProcessor processThrottled(String template, IContext context) {
return new IThrottledTemplateProcessor() {
};
}
public IThrottledTemplateProcessor processThrottled(TemplateSpec templateSpec, IContext context) {
return new IThrottledTemplateProcessor() {
};
}
}

View File

@@ -0,0 +1,5 @@
package org.thymeleaf;
public class TemplateSpec {
}

View File

@@ -0,0 +1,7 @@
package org.thymeleaf.context;
import org.thymeleaf.context.IContext;
public class Context implements IContext {
}

View File

@@ -0,0 +1,5 @@
package org.thymeleaf.context;
public interface IContext {
}

View File

@@ -13,7 +13,7 @@ import semmle.javascript.security.dataflow.StoredXssQuery
import DataFlow::PathGraph
/**
* An instance of `mysql.createConnection()`, tracked globally.
* Gets an instance of `mysql.createConnection()`, tracked globally.
*/
DataFlow::SourceNode mysqlConnection(DataFlow::TypeTracker t) {
t.start() and
@@ -23,7 +23,7 @@ DataFlow::SourceNode mysqlConnection(DataFlow::TypeTracker t) {
}
/**
* An instance of `mysql.createConnection()`, tracked globally.
* Gets an instance of `mysql.createConnection()`, tracked globally.
*/
DataFlow::SourceNode mysqlConnection() { result = mysqlConnection(DataFlow::TypeTracker::end()) }

View File

@@ -134,7 +134,7 @@ int getNumCharsInFunction(Function f) {
}
/**
* The maximum number of characters a feature can be.
* Gets the maximum number of characters a feature can be.
* The evaluator string limit is 5395415 characters. We choose a limit lower than this.
*/
private int getMaxChars() { result = 1000000 }

View File

@@ -12,7 +12,7 @@ import experimental.adaptivethreatmodeling.EndpointFeatures as EndpointFeatures
import experimental.adaptivethreatmodeling.EndpointTypes
import semmle.javascript.security.dataflow.NosqlInjectionCustomizations
/** The positive endpoint type for which you wish to find misclassified examples. */
/** Gets the positive endpoint type for which you wish to find misclassified examples. */
EndpointType getEndpointType() { result instanceof NosqlInjectionSinkType }
/** Get a positive endpoint. This will be run through the classifier to determine whether it is misclassified. */

View File

@@ -1,50 +1,62 @@
# NoSQL database query built from user-controlled sources (experimental)
If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.
If a database query is built from user-provided data without sufficient sanitization, a user may be able to run malicious database queries.
Note: This CodeQL query is an experimental query. Experimental queries generate alerts using machine learning. They might include more false positives but they will improve over time.
## Recommendation
Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements.
For NoSQL queries, make use of an operator like MongoDB's `$eq` to ensure that untrusted data is interpreted as a literal value and not as a query object.
Ensure that untrusted data is interpreted as a literal value and not as a query object, eg., by using an operator like MongoDB's `$eq`.
## Example
In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object.
In the following example, an `express.js` application is defining two endpoints that permit a user to query a MongoDB database.
The handler constructs two copies of the same SQL query involving user input taken from the request object, once unsafely using string concatenation, and once safely using query parameters.
In each case, the handler constructs two copies of the same query involving user input taken from the request object. In both handlers, the input is parsed using the `body-parser` library, which will transform the request data that arrives as a string to JSON objects.
In the first case, the query string `query1` is built by directly concatenating a user-supplied request parameter with some string literals. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack.
In the first case, `/search1`, the input is used as a query object. This means that a malicious user is able to inject queries that select more data than the developer intended.
In the second case, the parameter is embedded into the query string `query2` using query parameters. In this example, we use the API offered by the `pg` Postgres database connector library, but other libraries offer similar features. This version is immune to injection attacks.
In the second case, `/search2`, parts of the input are converted to a string representation and then used with the `$eq` operator to construct a query object.
```javascript
const app = require("express")(),
pg = require("pg"),
pool = new pg.Pool(config);
mongodb = require("mongodb"),
bodyParser = require('body-parser');
app.get("search", function handler(req, res) {
// BAD: the category might have SQL special characters in it
var query1 =
"SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" +
req.params.category +
"' ORDER BY PRICE";
pool.query(query1, [], function(err, results) {
// process results
});
const client = new MongoClient('mongodb://localhost:27017/test');
// GOOD: use parameters
var query2 =
"SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=$1" + " ORDER BY PRICE";
pool.query(query2, [req.params.category], function(err, results) {
// process results
});
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/search1", async function handler(req, res) {
await client.connect();
const db = client.db('test');
const doc = db.collection('doc');
const result = doc.find({
// BAD:
// This is vulnerable.
// Eg., req.body.title might be the object { $ne: "foobarbaz" }, and the
// endpoint would return all data.
title: req.body.title
});
res.send(await result);
});
app.get("/search2", async function handler(req, res) {
await client.connect();
const db = client.db('test');
const doc = db.collection('doc');
// GOOD:
// The input is converted to a string, and matched using the $eq operator.
// At most one datum is returned.
const result = await doc.find({ title: { $eq: `${req.body.title}` } });
res.send(await result);
});
```
## References
* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
* Acunetix Blog: [NoSQL Injections and How to Avoid Them](https://www.acunetix.com/blog/web-security-zone/nosql-injections/).
* MongoDB: [$eq operator](https://docs.mongodb.com/manual/reference/operator/query/eq).
* MongoDB: [$ne operator](https://docs.mongodb.com/manual/reference/operator/query/ne).

View File

@@ -1,5 +1,5 @@
# SQL database query built from user-controlled sources (experimental)
If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.
If a SQL query is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.
Note: This CodeQL query is an experimental query. Experimental queries generate alerts using machine learning. They might include more false positives but they will improve over time.
@@ -7,11 +7,8 @@ Note: This CodeQL query is an experimental query. Experimental queries generate
## Recommendation
Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements.
For NoSQL queries, make use of an operator like MongoDB's `$eq` to ensure that untrusted data is interpreted as a literal value and not as a query object.
## Example
In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object.
In the following example, an `express.js` application is defining two endpoints that permit a user to query a postgres database.
The handler constructs two copies of the same SQL query involving user input taken from the request object, once unsafely using string concatenation, and once safely using query parameters.
@@ -47,4 +44,3 @@ app.get("search", function handler(req, res) {
## References
* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
* MongoDB: [$eq operator](https://docs.mongodb.com/manual/reference/operator/query/eq).

View File

@@ -16,7 +16,7 @@ module ArrayTaintTracking {
}
/**
* A taint propagating data flow edge from `pred` to `succ` caused by a call `call` to a builtin array functions.
* Holds if there is a taint propagating data flow edge from `pred` to `succ` caused by a call `call` to a builtin array functions.
*/
predicate arrayFunctionTaintStep(DataFlow::Node pred, DataFlow::Node succ, DataFlow::CallNode call) {
// `array.map(function (elt, i, ary) { ... })`: if `array` is tainted, then so are
@@ -357,7 +357,7 @@ private module ArrayLibraries {
}
/**
* A call to a library that copies the elements of an array into another array.
* Gets a call to a library that copies the elements of an array into another array.
* E.g. `array-union` that creates a union of multiple arrays, or `array-uniq` that creates an array with unique elements.
*/
DataFlow::CallNode arrayCopyCall(DataFlow::Node array) {

View File

@@ -300,7 +300,7 @@ module DOM {
}
/**
* A data flow node that might refer to some form.
* Gets a data flow node that might refer to some form.
* Either by a read like `document.forms[0]`, or a property read from `document` with some constant property-name.
* E.g. if `<form name="foobar">..</form>` exists, then `document.foobar` refers to that form.
*/

View File

@@ -182,6 +182,8 @@ private class CloneStep extends PreCallGraphStep {
call = DataFlow::moduleImport(["clone", "fclone", "sort-keys", "camelcase-keys"]).getACall()
or
call = DataFlow::moduleMember("json-cycle", ["decycle", "retrocycle"]).getACall()
or
call = LodashUnderscore::member(["clone", "cloneDeep"]).getACall()
|
pred = call.getArgument(0) and
succ = call

View File

@@ -173,6 +173,24 @@ module HTML {
DocumentElement() { getName() = "html" }
}
/**
* An HTML `<iframe>` element.
*
* Example:
*
* ```
* <iframe src="https://test.local/somepage.html"></iframe>
* ```
*/
class IframeElement extends Element {
IframeElement() { getName() = "iframe" }
/**
* Gets the value of the `src` attribute.
*/
string getSourcePath() { result = getAttributeByName("src").getValue() }
}
/**
* An HTML `<script>` element.
*
@@ -207,6 +225,11 @@ module HTML {
*/
string getSourcePath() { result = getAttributeByName("src").getValue() }
/**
* Gets the value of the `integrity` attribute.
*/
string getIntegrityDigest() { result = getAttributeByName("integrity").getValue() }
/**
* Gets the folder relative to which the `src` attribute is resolved.
*/

View File

@@ -56,7 +56,7 @@ module JsonSchema {
/** Provides a model of the `ajv` library. */
module Ajv {
/** A method on `Ajv` that returns `this`. */
/** Gets a method on `Ajv` that returns `this`. */
private string chainedMethod() {
result =
["addSchema", "addMetaSchema", "removeSchema", "addFormat", "addKeyword", "removeKeyword"]
@@ -141,7 +141,7 @@ module JsonSchema {
/** Provides a model for working with the [`joi`](https://npmjs.org/package/joi) library. */
module Joi {
/** A schema created using `joi.object()` or other schemas that might refer an object schema. */
/** Gets a schema created using `joi.object()` or other schemas that might refer an object schema. */
private API::Node objectSchema() {
// A call that creates a schema that might be an object schema.
result =

View File

@@ -87,6 +87,15 @@ private DataFlow::Node getAValueExportedByPackage() {
result = getAnExportFromModule(mod)
)
or
// require("./other-module.js"); inside an AMD module.
exists(Module mod, CallExpr call |
call = getAValueExportedByPackage().asExpr() and
call = any(AmdModuleDefinition e).getARequireCall() and
mod = call.getAnArgument().(Import).getImportedModule()
|
result = getAnExportFromModule(mod)
)
or
// module.exports = class Foo {
// bar() {} // <- result
// static baz() {} // <- result

View File

@@ -503,7 +503,7 @@ class SsaExplicitDefinition extends SsaDefinition, TExplicitDef {
/** This SSA definition corresponds to the definition of `v` at `def`. */
predicate defines(VarDef d, SsaSourceVariable v) { this = TExplicitDef(_, _, d, v) }
/** The variable definition wrapped by this SSA definition. */
/** Gets the variable definition wrapped by this SSA definition. */
VarDef getDef() { this = TExplicitDef(_, _, result, _) }
/** Gets the basic block to which this definition belongs. */

View File

@@ -651,10 +651,18 @@ module DataFlow {
override string getPropertyName() { result = astNode.getArgument(1).getStringValue() }
override Node getRhs() {
exists(ObjectExpr obj | obj = astNode.getArgument(2) |
result = obj.getPropertyByName("value").getInit().flow()
exists(DataFlow::SourceNode descriptor |
descriptor = astNode.getArgument(2).flow().getALocalSource()
|
result =
descriptor
.getAPropertyWrite("get")
.getRhs()
.getALocalSource()
.(DataFlow::FunctionNode)
.getAReturn()
or
result = obj.getPropertyByName("get").getInit().flow().(DataFlow::FunctionNode).getAReturn()
result = descriptor.getAPropertyWrite("value").getRhs()
)
}

View File

@@ -787,16 +787,16 @@ class MemberKind extends string {
}
module MemberKind {
/** The kind of a method, such as `m() {}` */
/** Gets the kind of a method, such as `m() {}` */
MemberKind method() { result = "method" }
/** The kind of a getter accessor, such as `get f() {}`. */
/** Gets the kind of a getter accessor, such as `get f() {}`. */
MemberKind getter() { result = "getter" }
/** The kind of a setter accessor, such as `set f() {}`. */
/** Gets the kind of a setter accessor, such as `set f() {}`. */
MemberKind setter() { result = "setter" }
/** The `getter` and `setter` kinds. */
/** Gets the `getter` and `setter` kinds. */
MemberKind accessor() { result = getter() or result = setter() }
/**

View File

@@ -804,13 +804,13 @@ module TaintTracking {
}
/**
* A pseudo-property a `URL` that stores a value that can be obtained
* Gets a pseudo-property a `URL` that stores a value that can be obtained
* with a `get` or `getAll` call to the `searchParams` property.
*/
private string hiddenUrlPseudoProperty() { result = "$hiddenSearchPararms" }
/**
* A pseudo-property on a `URLSearchParams` that can be obtained
* Gets a pseudo-property on a `URLSearchParams` that can be obtained
* with a `get` or `getAll` call.
*/
private string getableUrlPseudoProperty() { result = "$gettableSearchPararms" }

View File

@@ -480,7 +480,7 @@ private module CachedSteps {
}
/**
* A step from `pred` to `succ` through a call to an identity function.
* Holds if there is a step from `pred` to `succ` through a call to an identity function.
*/
cached
predicate identityFunctionStep(DataFlow::Node pred, DataFlow::CallNode succ) {

View File

@@ -21,7 +21,7 @@ abstract class Dependency extends Locatable {
abstract predicate info(string id, string v);
/**
* A use of this dependency, which is of the given `kind`.
* Gets a use of this dependency, which is of the given `kind`.
*
* Currently, the only supported kinds are `"import"` and `"use"`.
*/

View File

@@ -99,7 +99,7 @@ private predicate isBrowserifyDependencyMap(ObjectExpr deps) {
}
/**
* A function that looks like a bundled module created
* Holds if `m` is a function that looks like a bundled module created
* by Webpack.
*
* Parameters must be named either `module` or `exports`,

View File

@@ -6,14 +6,14 @@ import javascript
private import semmle.javascript.security.dataflow.Xss as Xss
module Cheerio {
/** A reference to the `cheerio` function, possibly with a loaded DOM. */
/** Gets a reference to the `cheerio` function, possibly with a loaded DOM. */
private API::Node cheerioApi() {
result = API::moduleImport("cheerio")
or
result = cheerioApi().getMember(["load", "parseHTML"]).getReturn()
}
/** A reference to the `cheerio` function, possibly with a loaded DOM. */
/** Gets a reference to the `cheerio` function, possibly with a loaded DOM. */
DataFlow::SourceNode cheerioRef() { result = cheerioApi().getAUse() }
/**

View File

@@ -807,7 +807,7 @@ module ClientRequest {
*/
private module ApolloClient {
/**
* A function from `apollo-client` that accepts an options object that may contain a `uri` property.
* Gets a function from `apollo-client` that accepts an options object that may contain a `uri` property.
*/
API::Node apolloUriCallee() {
result = API::moduleImport("apollo-link-http").getMember(["HttpLink", "createHttpLink"])

View File

@@ -51,12 +51,12 @@ module CookieWrites {
}
/**
* The flag that indicates that a cookie is secure.
* Gets the flag that indicates that a cookie is secure.
*/
string secure() { result = "secure" }
/**
* The flag that indicates that a cookie is HttpOnly.
* Gets the flag that indicates that a cookie is HttpOnly.
*/
string httpOnly() { result = "httpOnly" }
}

View File

@@ -261,4 +261,15 @@ module Hapi {
override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) }
}
/**
* A return from a route handler.
*/
private class HandlerReturn extends HTTP::ResponseSendArgument {
RouteHandler handler;
HandlerReturn() { this = handler.(DataFlow::FunctionNode).getAReturn().asExpr() }
override RouteHandler getRouteHandler() { result = handler }
}
}

View File

@@ -22,7 +22,7 @@ private module Immutable {
}
/**
* An import of the `Immutable` library.
* Gets an import of the `Immutable` library.
*/
API::Node immutableImport() {
result = API::moduleImport("immutable")
@@ -31,7 +31,7 @@ private module Immutable {
}
/**
* An instance of any immutable collection.
* Gets an instance of any immutable collection.
*
* This predicate keeps track of which values in the program are Immutable collections.
*/

View File

@@ -36,10 +36,10 @@ module LdapJS {
/** A creation of an LDAPjs filter, or object containing a filter, that doesn't sanitizes the input. */
abstract class TaintPreservingLdapFilterStep extends DataFlow::Node {
/** The input that creates (part of) an LDAPjs filter. */
/** Gets the input that creates (part of) an LDAPjs filter. */
abstract DataFlow::Node getInput();
/** The resulting LDAPjs filter. */
/** Gets the resulting LDAPjs filter. */
abstract DataFlow::Node getOutput();
}

View File

@@ -80,7 +80,7 @@ module Markdown {
*/
private module Unified {
/**
* The creation of a parser from `unified`.
* Gets a parser from `unified`.
* The `remark` module is a shorthand that initializes `unified` with a markdown parser.
*/
DataFlow::CallNode unified() {
@@ -152,7 +152,7 @@ module Markdown {
*/
private module MarkdownIt {
/**
* The creation of a parser from `markdown-it`.
* Gets a creation of a parser from `markdown-it`.
*/
private API::Node markdownIt() {
exists(API::InvokeNode call |

View File

@@ -8,7 +8,7 @@ private module Micro {
private import DataFlow
/**
* A node that should be interpreted as a route handler, to use as starting
* Gets a node that should be interpreted as a route handler, to use as starting
* point for back-tracking.
*/
Node microRouteHandlerSink() {

View File

@@ -493,7 +493,7 @@ module NodeJSLib {
*/
module FS {
/**
* A member `member` from module `fs` or its drop-in replacements `graceful-fs`, `fs-extra`, `original-fs`.
* Gets a member `member` from module `fs` or its drop-in replacements `graceful-fs`, `fs-extra`, `original-fs`.
*/
DataFlow::SourceNode moduleMember(string member) {
result = fsModule(DataFlow::TypeTracker::end()).getAPropertyRead(member)

View File

@@ -9,12 +9,12 @@ import javascript
*/
module Puppeteer {
/**
* A reference to a module import of puppeteer.
* Gets a reference to a module import of puppeteer.
*/
private API::Node puppeteer() { result = API::moduleImport(["puppeteer", "puppeteer-core"]) }
/**
* A reference to a `Browser` from puppeteer.
* Gets a reference to a `Browser` from puppeteer.
*/
private API::Node browser() {
result = API::Node::ofType("puppeteer", "Browser")
@@ -25,7 +25,7 @@ module Puppeteer {
}
/**
* A reference to a `Page` from puppeteer.
* Gets a reference to a `Page` from puppeteer.
*/
API::Node page() {
result = API::Node::ofType("puppeteer", "Page")
@@ -38,7 +38,7 @@ module Puppeteer {
}
/**
* A reference to a `Target` from puppeteer.
* Gets a reference to a `Target` from puppeteer.
*/
private API::Node target() {
result = API::Node::ofType("puppeteer", "Target")
@@ -51,7 +51,7 @@ module Puppeteer {
}
/**
* A reference to a `BrowserContext` from puppeteer.
* Gets a reference to a `BrowserContext` from puppeteer.
*/
private API::Node context() {
result = API::Node::ofType("puppeteer", "BrowserContext")

View File

@@ -27,7 +27,7 @@ module Redux {
importer.getADependenciesObject("").getADependency(dependency.getPackageName(), _)
}
/** A package that can be considered an entry point for a Redux app. */
/** Gets a package that can be considered an entry point for a Redux app. */
private PackageJSON entryPointPackage() {
result = getPackageJson(any(StoreCreation c).getFile())
or

View File

@@ -376,7 +376,7 @@ private module Sqlite {
result = API::Node::ofType("sqlite3", "Database")
}
/** A call to a query method on a Sqlite database instance that returns the same instance. */
/** Gets a call to a query method on a Sqlite database instance that returns the same instance. */
private API::Node getAChainingQueryCall() {
result = database().getMember(["all", "each", "exec", "get", "run"]).getReturn()
}

View File

@@ -43,7 +43,7 @@ module Vue {
*/
DataFlow::SourceNode vue() { result = vueLibrary().getAnImmediateUse() }
/** An API node referring to a component or `Vue`. */
/** Gets an API node referring to a component or `Vue`. */
private API::Node component() {
result = vueLibrary()
or
@@ -683,7 +683,7 @@ module Vue {
}
}
/** An API node referring to a `RouteConfig` being passed to `vue-router`. */
/** Gets an API node referring to a `RouteConfig` being passed to `vue-router`. */
private API::Node routeConfig() {
result = API::moduleImport("vue-router").getParameter(0).getMember("routes").getAMember()
or

View File

@@ -376,7 +376,7 @@ module Vuex {
importer.getADependenciesObject("").getADependency(dependency.getPackageName(), _)
}
/** A package that can be considered an entry point for a Vuex app. */
/** Gets a package that can be considered an entry point for a Vuex app. */
private PackageJSON entryPointPackage() {
result = getPackageJson(storeRef().getAnImmediateUse().getFile())
or

View File

@@ -60,7 +60,7 @@ module XML {
}
/**
* A document from the `libxmljs` library.
* Gets a document from the `libxmljs` library.
* The API is based on https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/libxmljs/index.d.ts
*/
private API::Node doc() {
@@ -74,7 +74,7 @@ module XML {
}
/**
* An `Element` from the `libxmljs` library.
* Gets an `Element` from the `libxmljs` library.
*/
private API::Node element() {
result = doc().getMember(["child", "get", "node", "root"]).getReturn()
@@ -91,7 +91,7 @@ module XML {
}
/**
* An `Attr` from the `libxmljs` library.
* Gets an `Attr` from the `libxmljs` library.
*/
private API::Node attr() {
result = element().getMember("attr").getReturn()

View File

@@ -21,7 +21,8 @@
*/
private import javascript
private import internal.Shared as Shared
private import internal.ApiGraphModels as Shared
private import internal.ApiGraphModelsSpecific as Specific
import Shared::ModelInput as ModelInput
import Shared::ModelOutput as ModelOutput
@@ -39,7 +40,7 @@ private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
*/
private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, string kind) {
exists(API::Node predNode, API::Node succNode |
ModelOutput::summaryStep(predNode, succNode, kind) and
Specific::summaryStep(predNode, succNode, kind) and
pred = predNode.getARhs() and
succ = succNode.getAnImmediateUse()
)

View File

@@ -56,12 +56,13 @@
* the type is related to the `foo` package but is not intended to match a static type.
*/
private import Impl as Impl
import AccessPathSyntax
private import ApiGraphModelsSpecific as Specific
private class Unit = Impl::Unit;
private class Unit = Specific::Unit;
private module API = Impl::API;
private module API = Specific::API;
private import Specific::AccessPathSyntax
/** Module containing hooks for providing input data to be interpreted as a model. */
module ModelInput {
@@ -230,7 +231,7 @@ string getAPackageAlias(string package) {
* Holds if CSV rows involving `package` might be relevant for the analysis of this database.
*/
private predicate isRelevantPackage(string package) {
Impl::isPackageUsed(package)
Specific::isPackageUsed(package)
or
exists(string other |
isRelevantPackage(other) and
@@ -268,28 +269,25 @@ private class AccessPathRange extends AccessPath::Range {
* Gets a successor of `node` in the API graph.
*/
bindingset[token]
private API::Node getSuccessorFromNode(API::Node node, AccessPathToken token) {
API::Node getSuccessorFromNode(API::Node node, AccessPathToken token) {
// API graphs use the same label for arguments and parameters. An edge originating from a
// use-node represents be an argument, and an edge originating from a def-node represents a parameter.
// We just map both to the same thing.
token.getName() = ["Argument", "Parameter"] and
result = node.getParameter(getAnIntFromStringUnbounded(token.getAnArgument()))
or
token.getName() = "Member" and
result = node.getMember(token.getAnArgument())
or
token.getName() = "ReturnValue" and
result = node.getReturn()
or
// Language-specific tokens
result = Impl::getExtraSuccessorFromNode(node, token)
result = Specific::getExtraSuccessorFromNode(node, token)
}
/**
* Gets an API-graph successor for the given invocation.
*/
bindingset[token]
private API::Node getSuccessorFromInvoke(API::InvokeNode invoke, AccessPathToken token) {
API::Node getSuccessorFromInvoke(Specific::InvokeNode invoke, AccessPathToken token) {
token.getName() = "Argument" and
(
result = invoke.getParameter(getAnIntFromStringUnbounded(token.getAnArgument()))
@@ -303,18 +301,18 @@ private API::Node getSuccessorFromInvoke(API::InvokeNode invoke, AccessPathToken
result = invoke.getReturn()
or
// Language-specific tokens
result = Impl::getExtraSuccessorFromInvoke(invoke, token)
result = Specific::getExtraSuccessorFromInvoke(invoke, token)
}
/**
* Holds if `invoke` invokes a call-site filter given by `token`.
*/
pragma[inline]
private predicate invocationMatchesCallSiteFilter(API::InvokeNode invoke, AccessPathToken token) {
private predicate invocationMatchesCallSiteFilter(Specific::InvokeNode invoke, AccessPathToken token) {
token.getName() = "WithArity" and
invoke.getNumArgument() = getAnIntFromStringUnbounded(token.getAnArgument())
or
Impl::invocationMatchesExtraCallSiteFilter(invoke, token)
Specific::invocationMatchesExtraCallSiteFilter(invoke, token)
}
/**
@@ -324,10 +322,6 @@ pragma[nomagic]
API::Node getNodeFromPath(string package, string type, AccessPath path, int n) {
isRelevantFullPath(package, type, path) and
(
type = "" and
n = 0 and
result = API::moduleImport(package)
or
n = 0 and
exists(string package2, string type2, AccessPath path2 |
typeModel(package, type, package2, type2, path2) and
@@ -335,7 +329,7 @@ API::Node getNodeFromPath(string package, string type, AccessPath path, int n) {
)
or
// Language-specific cases, such as handling of global variables
result = Impl::getExtraNodeFromPath(package, type, path, n)
result = Specific::getExtraNodeFromPath(package, type, path, n)
)
or
result = getSuccessorFromNode(getNodeFromPath(package, type, path, n - 1), path.getToken(n - 1))
@@ -355,62 +349,18 @@ API::Node getNodeFromPath(string package, string type, AccessPath path) {
*
* Unlike `getNodeFromPath`, the `path` may end with one or more call-site filters.
*/
API::InvokeNode getInvocationFromPath(string package, string type, AccessPath path, int n) {
result = getNodeFromPath(package, type, path, n).getAnInvocation()
Specific::InvokeNode getInvocationFromPath(string package, string type, AccessPath path, int n) {
result = Specific::getAnInvocationOf(getNodeFromPath(package, type, path, n))
or
result = getInvocationFromPath(package, type, path, n - 1) and
invocationMatchesCallSiteFilter(result, path.getToken(n - 1))
}
/** Gets an invocation identified by the given `(package, type, path)` tuple. */
API::InvokeNode getInvocationFromPath(string package, string type, AccessPath path) {
Specific::InvokeNode getInvocationFromPath(string package, string type, AccessPath path) {
result = getInvocationFromPath(package, type, path, path.getNumToken())
}
/**
* Holds if a summary edge with the given `input, output, kind` columns have a `package, type, path` tuple
* that resolves to `baseNode`.
*/
private predicate resolvedSummaryBase(
API::InvokeNode baseNode, AccessPath input, AccessPath output, string kind
) {
exists(string package, string type, AccessPath path |
summaryModel(package, type, path, input, output, kind) and
baseNode = getInvocationFromPath(package, type, path)
)
}
/**
* Holds if `path` is an input or output spec for a summary with the given `base` node.
*/
pragma[nomagic]
private predicate relevantInputOutputPath(API::InvokeNode base, AccessPath path) {
resolvedSummaryBase(base, path, _, _)
or
resolvedSummaryBase(base, _, path, _)
}
/**
* Gets the API node for the first `n` tokens of the given input/output path, evaluated relative to `baseNode`.
*/
private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPath path, int n) {
relevantInputOutputPath(baseNode, path) and
(
n = 1 and
result = getSuccessorFromInvoke(baseNode, path.getToken(0))
or
result =
getSuccessorFromNode(getNodeFromInputOutputPath(baseNode, path, n - 1), path.getToken(n - 1))
)
}
/**
* Gets the API node for the given input/output path, evaluated relative to `baseNode`.
*/
private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPath path) {
result = getNodeFromInputOutputPath(baseNode, path, path.getNumToken())
}
/**
* Convenience-predicate for extracting two capture groups at once.
*/
@@ -519,13 +469,25 @@ module ModelOutput {
}
/**
* Holds if a CSV summary contributed the step `pred -> succ` of the given `kind`.
* Holds if a relevant CSV summary row has the given `kind`, `input` and `output`.
*/
predicate summaryStep(API::Node pred, API::Node succ, string kind) {
exists(API::InvokeNode base, AccessPath input, AccessPath output |
resolvedSummaryBase(base, input, output, kind) and
pred = getNodeFromInputOutputPath(base, input) and
succ = getNodeFromInputOutputPath(base, output)
predicate summaryModel(string input, string output, string kind) {
exists(string package |
isRelevantPackage(package) and
summaryModel(package, _, _, input, output, kind)
)
}
/**
* Holds if a summary edge with the given `input, output, kind` columns have a `package, type, path` tuple
* that resolves to `baseNode`.
*/
predicate resolvedSummaryBase(
Specific::InvokeNode baseNode, AccessPath input, AccessPath output, string kind
) {
exists(string package, string type, AccessPath path |
summaryModel(package, type, path, input, output, kind) and
baseNode = getInvocationFromPath(package, type, path)
)
}

Some files were not shown because too many files have changed in this diff Show More