зеркало из https://github.com/github/codeql.git
Merge pull request #336 from aschackmull/java/dataflow-cleanup
Approved by yh-semmle
This commit is contained in:
Коммит
c78f3f8edf
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ private module ImplCommon {
|
||||||
node1.(ArgumentNode).argumentOf(call, i1) and
|
node1.(ArgumentNode).argumentOf(call, i1) and
|
||||||
node2.getPreUpdateNode().(ArgumentNode).argumentOf(call, i2) and
|
node2.getPreUpdateNode().(ArgumentNode).argumentOf(call, i2) and
|
||||||
compatibleTypes(node1.getTypeBound(), f.getType()) and
|
compatibleTypes(node1.getTypeBound(), f.getType()) and
|
||||||
compatibleTypes(node2.getTypeBound(), f.getDeclaringType())
|
compatibleTypes(node2.getTypeBound(), f.getContainerType())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ private module ImplCommon {
|
||||||
setterReturn(p, f) and
|
setterReturn(p, f) and
|
||||||
arg.argumentOf(node2.asExpr(), _) and
|
arg.argumentOf(node2.asExpr(), _) and
|
||||||
compatibleTypes(node1.getTypeBound(), f.getType()) and
|
compatibleTypes(node1.getTypeBound(), f.getType()) and
|
||||||
compatibleTypes(node2.getTypeBound(), f.getDeclaringType())
|
compatibleTypes(node2.getTypeBound(), f.getContainerType())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ private module ImplCommon {
|
||||||
viableParamArg(p, arg) and
|
viableParamArg(p, arg) and
|
||||||
getter(p, f) and
|
getter(p, f) and
|
||||||
arg.argumentOf(node2.asExpr(), _) and
|
arg.argumentOf(node2.asExpr(), _) and
|
||||||
compatibleTypes(node1.getTypeBound(), f.getDeclaringType()) and
|
compatibleTypes(node1.getTypeBound(), f.getContainerType()) and
|
||||||
compatibleTypes(node2.getTypeBound(), f.getType())
|
compatibleTypes(node2.getTypeBound(), f.getType())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,18 +69,9 @@ class Content extends TContent {
|
||||||
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
|
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
|
||||||
}
|
}
|
||||||
/** Gets the type of the object containing this content. */
|
/** Gets the type of the object containing this content. */
|
||||||
abstract RefType getDeclaringType();
|
abstract RefType getContainerType();
|
||||||
/** Gets the type of this content. */
|
/** Gets the type of this content. */
|
||||||
abstract Type getType();
|
abstract Type getType();
|
||||||
/**
|
|
||||||
* Holds if this content may contain an object of the same type as the one
|
|
||||||
* that contains this content, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
predicate isSelfRef() { none() }
|
|
||||||
}
|
}
|
||||||
private class FieldContent extends Content, TFieldContent {
|
private class FieldContent extends Content, TFieldContent {
|
||||||
Field f;
|
Field f;
|
||||||
|
@ -90,17 +81,17 @@ private class FieldContent extends Content, TFieldContent {
|
||||||
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||||
f.getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
f.getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
||||||
}
|
}
|
||||||
override RefType getDeclaringType() { result = f.getDeclaringType() }
|
override RefType getContainerType() { result = f.getDeclaringType() }
|
||||||
override Type getType() { result = f.getType() }
|
override Type getType() { result = f.getType() }
|
||||||
}
|
}
|
||||||
private class CollectionContent extends Content, TCollectionContent {
|
private class CollectionContent extends Content, TCollectionContent {
|
||||||
override string toString() { result = "collection" }
|
override string toString() { result = "collection" }
|
||||||
override RefType getDeclaringType() { none() }
|
override RefType getContainerType() { none() }
|
||||||
override Type getType() { none() }
|
override Type getType() { none() }
|
||||||
}
|
}
|
||||||
private class ArrayContent extends Content, TArrayContent {
|
private class ArrayContent extends Content, TArrayContent {
|
||||||
override string toString() { result = "array" }
|
override string toString() { result = "array" }
|
||||||
override RefType getDeclaringType() { none() }
|
override RefType getContainerType() { none() }
|
||||||
override Type getType() { none() }
|
override Type getType() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +123,11 @@ RefType getErasedRepr(Type t) {
|
||||||
result instanceof VoidType // stub implementation
|
result instanceof VoidType // stub implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets a string representation of a type returned by `getErasedRepr`. */
|
||||||
|
string ppReprType(Type t) {
|
||||||
|
result = t.toString()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
||||||
* a node of type `t1` to a node of type `t2`.
|
* a node of type `t1` to a node of type `t2`.
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ private module ImplCommon {
|
||||||
node1.(ArgumentNode).argumentOf(call, i1) and
|
node1.(ArgumentNode).argumentOf(call, i1) and
|
||||||
node2.getPreUpdateNode().(ArgumentNode).argumentOf(call, i2) and
|
node2.getPreUpdateNode().(ArgumentNode).argumentOf(call, i2) and
|
||||||
compatibleTypes(node1.getTypeBound(), f.getType()) and
|
compatibleTypes(node1.getTypeBound(), f.getType()) and
|
||||||
compatibleTypes(node2.getTypeBound(), f.getDeclaringType())
|
compatibleTypes(node2.getTypeBound(), f.getContainerType())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ private module ImplCommon {
|
||||||
setterReturn(p, f) and
|
setterReturn(p, f) and
|
||||||
arg.argumentOf(node2.asExpr(), _) and
|
arg.argumentOf(node2.asExpr(), _) and
|
||||||
compatibleTypes(node1.getTypeBound(), f.getType()) and
|
compatibleTypes(node1.getTypeBound(), f.getType()) and
|
||||||
compatibleTypes(node2.getTypeBound(), f.getDeclaringType())
|
compatibleTypes(node2.getTypeBound(), f.getContainerType())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ private module ImplCommon {
|
||||||
viableParamArg(p, arg) and
|
viableParamArg(p, arg) and
|
||||||
getter(p, f) and
|
getter(p, f) and
|
||||||
arg.argumentOf(node2.asExpr(), _) and
|
arg.argumentOf(node2.asExpr(), _) and
|
||||||
compatibleTypes(node1.getTypeBound(), f.getDeclaringType()) and
|
compatibleTypes(node1.getTypeBound(), f.getContainerType()) and
|
||||||
compatibleTypes(node2.getTypeBound(), f.getType())
|
compatibleTypes(node2.getTypeBound(), f.getType())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -724,76 +724,27 @@ private predicate localFlowBigStep(
|
||||||
localFlowExit(node2, config)
|
localFlowExit(node2, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `f` may contain an object of the same type, `t`, as the one
|
|
||||||
* that contains `f`, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
private predicate selfRef(Content f, RefType t) {
|
|
||||||
t = f.getDeclaringType() and
|
|
||||||
f.isSelfRef()
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TFlowContainer =
|
|
||||||
TRegularContent(Content f) { not selfRef(f, _) } or
|
|
||||||
TSelfRefContent(RefType t) { selfRef(_, t) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A `Content` or a `Content` abstracted as its declaring type.
|
|
||||||
*
|
|
||||||
* Sequences of one or more `Content`s in the same declaring type for which
|
|
||||||
* `isSelfRef()` holds are represented as a single `FlowContainer` in an
|
|
||||||
* `AccessPath`.
|
|
||||||
*/
|
|
||||||
private class FlowContainer extends TFlowContainer {
|
|
||||||
string toString() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.toString())
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and result = t.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
predicate usesContent(Content f) {
|
|
||||||
this = TRegularContent(f)
|
|
||||||
or
|
|
||||||
exists(RefType t | this = TSelfRefContent(t) and selfRef(f, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
RefType getContainerType() {
|
|
||||||
exists(Content f | this = TRegularContent(f) and result = f.getDeclaringType())
|
|
||||||
or
|
|
||||||
this = TSelfRefContent(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private newtype TAccessPathFront =
|
private newtype TAccessPathFront =
|
||||||
TFrontNil(Type t) or
|
TFrontNil(Type t) or
|
||||||
TFrontHead(FlowContainer f)
|
TFrontHead(Content f)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The front of an `AccessPath`. This is either a head or a nil.
|
* The front of an `AccessPath`. This is either a head or a nil.
|
||||||
*/
|
*/
|
||||||
private class AccessPathFront extends TAccessPathFront {
|
private class AccessPathFront extends TAccessPathFront {
|
||||||
string toString() {
|
string toString() {
|
||||||
exists(Type t | this = TFrontNil(t) | result = t.toString())
|
exists(Type t | this = TFrontNil(t) | result = ppReprType(t))
|
||||||
or
|
or
|
||||||
exists(FlowContainer f | this = TFrontHead(f) | result = f.toString())
|
exists(Content f | this = TFrontHead(f) | result = f.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TFrontNil(result)
|
this = TFrontNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TFrontHead(head) | result = head.getContainerType())
|
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate headUsesContent(Content f) {
|
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||||
exists(FlowContainer fc |
|
|
||||||
fc.usesContent(f) and
|
|
||||||
this = TFrontHead(fc)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
private class AccessPathFrontNil extends AccessPathFront, TFrontNil { }
|
||||||
|
@ -1004,7 +955,7 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
|
||||||
|
|
||||||
private newtype TAccessPath =
|
private newtype TAccessPath =
|
||||||
TNil(Type t) or
|
TNil(Type t) or
|
||||||
TCons(FlowContainer f, int len) { len in [1 .. 5] }
|
TCons(Content f, int len) { len in [1 .. 5] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||||
|
@ -1016,7 +967,7 @@ private newtype TAccessPath =
|
||||||
private class AccessPath extends TAccessPath {
|
private class AccessPath extends TAccessPath {
|
||||||
abstract string toString();
|
abstract string toString();
|
||||||
|
|
||||||
FlowContainer getHead() { this = TCons(result, _) }
|
Content getHead() { this = TCons(result, _) }
|
||||||
|
|
||||||
int len() {
|
int len() {
|
||||||
this = TNil(_) and result = 0
|
this = TNil(_) and result = 0
|
||||||
|
@ -1027,27 +978,27 @@ private class AccessPath extends TAccessPath {
|
||||||
Type getType() {
|
Type getType() {
|
||||||
this = TNil(result)
|
this = TNil(result)
|
||||||
or
|
or
|
||||||
exists(FlowContainer head | this = TCons(head, _) | result = head.getContainerType())
|
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract AccessPathFront getFront();
|
abstract AccessPathFront getFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathNil extends AccessPath, TNil {
|
private class AccessPathNil extends AccessPath, TNil {
|
||||||
override string toString() { exists(Type t | this = TNil(t) | result = t.toString()) }
|
override string toString() { exists(Type t | this = TNil(t) | result = ppReprType(t)) }
|
||||||
|
|
||||||
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
override AccessPathFront getFront() { exists(Type t | this = TNil(t) | result = TFrontNil(t)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPathCons extends AccessPath, TCons {
|
private class AccessPathCons extends AccessPath, TCons {
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(FlowContainer f, int len | this = TCons(f, len) |
|
exists(Content f, int len | this = TCons(f, len) |
|
||||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AccessPathFront getFront() {
|
override AccessPathFront getFront() {
|
||||||
exists(FlowContainer f | this = TCons(f, _) | result = TFrontHead(f))
|
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,20 +118,10 @@ class Content extends TContent {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the type of the object containing this content. */
|
/** Gets the type of the object containing this content. */
|
||||||
abstract RefType getDeclaringType();
|
abstract RefType getContainerType();
|
||||||
|
|
||||||
/** Gets the type of this content. */
|
/** Gets the type of this content. */
|
||||||
abstract Type getType();
|
abstract Type getType();
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if this content may contain an object of the same type as the one
|
|
||||||
* that contains this content, and if this fact should be used to compress
|
|
||||||
* access paths.
|
|
||||||
*
|
|
||||||
* Examples include the tail pointer in a linked list or the left and right
|
|
||||||
* pointers in a binary tree.
|
|
||||||
*/
|
|
||||||
predicate isSelfRef() { none() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FieldContent extends Content, TFieldContent {
|
private class FieldContent extends Content, TFieldContent {
|
||||||
|
@ -147,17 +137,15 @@ private class FieldContent extends Content, TFieldContent {
|
||||||
f.getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
f.getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
||||||
}
|
}
|
||||||
|
|
||||||
override RefType getDeclaringType() { result = f.getDeclaringType() }
|
override RefType getContainerType() { result = f.getDeclaringType() }
|
||||||
|
|
||||||
override Type getType() { result = getFieldTypeBound(f) }
|
override Type getType() { result = getFieldTypeBound(f) }
|
||||||
|
|
||||||
override predicate isSelfRef() { compatibleTypes(getDeclaringType(), getType()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CollectionContent extends Content, TCollectionContent {
|
private class CollectionContent extends Content, TCollectionContent {
|
||||||
override string toString() { result = "collection" }
|
override string toString() { result = "collection" }
|
||||||
|
|
||||||
override RefType getDeclaringType() { none() }
|
override RefType getContainerType() { none() }
|
||||||
|
|
||||||
override Type getType() { none() }
|
override Type getType() { none() }
|
||||||
}
|
}
|
||||||
|
@ -165,7 +153,7 @@ private class CollectionContent extends Content, TCollectionContent {
|
||||||
private class ArrayContent extends Content, TArrayContent {
|
private class ArrayContent extends Content, TArrayContent {
|
||||||
override string toString() { result = "array" }
|
override string toString() { result = "array" }
|
||||||
|
|
||||||
override RefType getDeclaringType() { none() }
|
override RefType getContainerType() { none() }
|
||||||
|
|
||||||
override Type getType() { none() }
|
override Type getType() { none() }
|
||||||
}
|
}
|
||||||
|
@ -212,6 +200,13 @@ RefType getErasedRepr(Type t) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gets a string representation of a type returned by `getErasedRepr`. */
|
||||||
|
string ppReprType(Type t) {
|
||||||
|
if t.(BoxedType).getPrimitiveType().getName() = "double"
|
||||||
|
then result = "Number"
|
||||||
|
else result = t.toString()
|
||||||
|
}
|
||||||
|
|
||||||
private predicate canContainBool(Type t) {
|
private predicate canContainBool(Type t) {
|
||||||
t instanceof BooleanType or
|
t instanceof BooleanType or
|
||||||
any(BooleanType b).(RefType).getASourceSupertype+() = t
|
any(BooleanType b).(RefType).getASourceSupertype+() = t
|
||||||
|
@ -227,12 +222,9 @@ predicate compatibleTypes(Type t1, Type t2) {
|
||||||
e1 = getErasedRepr(t1) and
|
e1 = getErasedRepr(t1) and
|
||||||
e2 = getErasedRepr(t2)
|
e2 = getErasedRepr(t2)
|
||||||
|
|
|
|
||||||
/*
|
// Because of `getErasedRepr`, `erasedHaveIntersection` is a sufficient
|
||||||
* Because of `getErasedRepr`, `erasedHaveIntersection` is a sufficient
|
// compatibility check, but `conContainBool` is kept as a dummy disjunct
|
||||||
* compatibility check, but `conContainBool` is kept as a dummy disjunct
|
// to get the proper join-order.
|
||||||
* to get the proper join-order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
erasedHaveIntersection(e1, e2)
|
erasedHaveIntersection(e1, e2)
|
||||||
or
|
or
|
||||||
canContainBool(e1) and canContainBool(e2)
|
canContainBool(e1) and canContainBool(e2)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче