Merge pull request #15406 from hvitved/csharp/no-stats-experiment

C#: Remove all DB stats
This commit is contained in:
Tom Hvitved
2024-02-26 13:40:37 +01:00
committed by GitHub
11 changed files with 109 additions and 41769 deletions

View File

@@ -159,6 +159,11 @@ private module Annotations {
getNoFlagsNullability(result) = getChildNullability(annotations.getNullability(), i)
}
pragma[nomagic]
private Nullability getChildNullability0(Nullability n, int i) {
nullability_parent(getNullability(result), i, getNullability(n))
}
/**
* Gets the `i`th child of nullability `n`.
* Returns `n` if the nullability is not explicitly
@@ -167,9 +172,10 @@ private module Annotations {
*/
bindingset[i]
Nullability getChildNullability(Nullability n, int i) {
if nullability_parent(_, i, getNullability(n))
then nullability_parent(getNullability(result), i, getNullability(n))
else result = n
result = getChildNullability0(n, i)
or
not exists(getChildNullability0(n, i)) and
result = n
}
/**
@@ -276,6 +282,11 @@ private Annotations::Nullability getElementNullability(@has_type_annotation elem
else result instanceof Annotations::NoNullability
}
pragma[nomagic]
private predicate isNoFlagsNoNullability(Annotations::TypeAnnotations annotations) {
Annotations::getNoFlagsNullability(annotations) instanceof Annotations::NoNullability
}
private newtype TAnnotatedType =
TAnnotatedTypeNullability(Type type, Annotations::TypeAnnotations annotations) {
Annotations::elementTypeAnnotations(_, type, annotations)
@@ -288,7 +299,7 @@ private newtype TAnnotatedType =
Annotations::getNoFlagsNullability(annotations) = getTypeParameterNullability(_, type)
or
// All types have at least one annotated type
Annotations::getNoFlagsNullability(annotations) instanceof Annotations::NoNullability
isNoFlagsNoNullability(annotations) and exists(type)
or
exists(AnnotatedArrayType at |
type = at.getType().(ArrayType).getElementType() and

View File

@@ -95,10 +95,16 @@ private string getTypeArgumentsToString(ConstructedGeneric cg) {
strictconcat(Type t, int i | t = cg.getTypeArgument(i) | t.toStringWithTypes(), ", " order by i)
}
pragma[nomagic]
private string getTypeArgumentName(ConstructedGeneric cg, int i) {
result = cg.getTypeArgument(i).getName()
}
/** Gets the concatenation of the `getName()` of type arguments. */
language[monotonicAggregates]
private string getTypeArgumentsNames(ConstructedGeneric cg) {
result = strictconcat(Type t, int i | t = cg.getTypeArgument(i) | t.getName(), "," order by i)
result =
strictconcat(int i | exists(cg.getTypeArgument(i)) | getTypeArgumentName(cg, i), "," order by i)
}
/**
@@ -197,9 +203,9 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
// A<int>.B<T2> is a partially constructed UnboundGenericClass and
// A<int>.B<int> is a ConstructedGenericClass.
exists(ConstructedGeneric c, UnboundGeneric u, int tpi |
this = u.getTypeParameter(tpi) and
this = u.getTypeParameter(pragma[only_bind_into](tpi)) and
(u = c.getUnboundGeneric() or u = c.getUnboundDeclaration()) and
result = c.getTypeArgument(tpi)
result = c.getTypeArgument(pragma[only_bind_into](tpi))
)
}

View File

@@ -108,28 +108,29 @@ private predicate hasMemberCompatibleWithInterfaceMember(ValueOrRefType t, Virtu
*/
pragma[nomagic]
private Virtualizable getACompatibleInterfaceMember(Virtualizable m) {
result = getACompatibleInterfaceMemberAux(m) and
(
exists(ValueOrRefType declType | result = getACompatibleInterfaceMemberAux(m, declType) |
// If there is both an implicit and an explicit compatible member
// in the same type, then the explicit implementation must be used
not result = getACompatibleExplicitInterfaceMember(_, m.getDeclaringType())
not result = getACompatibleExplicitInterfaceMember(_, declType)
or
result = getACompatibleExplicitInterfaceMember(m, m.getDeclaringType())
result = getACompatibleExplicitInterfaceMember(m, declType)
)
}
pragma[nomagic]
private Virtualizable getACompatibleExplicitInterfaceMember(Virtualizable m, ValueOrRefType declType) {
result = getACompatibleInterfaceMemberAux(m) and
declType = m.getDeclaringType() and
result = getACompatibleInterfaceMemberAux(m, declType) and
m.implementsExplicitInterface()
}
pragma[nomagic]
private Virtualizable getACompatibleInterfaceMemberAux(Virtualizable m) {
result = getACompatibleInterfaceAccessor(m) or
result = getACompatibleInterfaceIndexer(m) or
result = getACompatibleRelevantInterfaceMember(m)
private Virtualizable getACompatibleInterfaceMemberAux(Virtualizable m, ValueOrRefType declType) {
(
result = getACompatibleInterfaceAccessor(m) or
result = getACompatibleInterfaceIndexer(m) or
result = getACompatibleRelevantInterfaceMember(m)
) and
declType = m.getDeclaringType()
}
/**
@@ -182,13 +183,16 @@ ValueOrRefType getAPossibleImplementor(Interface i) {
not result instanceof Interface
}
pragma[nomagic]
private Type getParameterType(Parameterizable p, int i) { result = p.getParameter(i).getType() }
private Indexer getACompatibleInterfaceIndexer0(Indexer i, int j) {
result = getACompatibleInterfaceIndexerCandidate(i) and
convIdentity(i.getType(), result.getType()) and
j = -1
or
result = getACompatibleInterfaceIndexer0(i, j - 1) and
convIdentity(i.getParameter(j).getType(), result.getParameter(j).getType())
convIdentity(getParameterType(i, j), getParameterType(result, j))
}
/**

View File

@@ -49,11 +49,20 @@ module QualifiedName<QualifiedNameInputSig Input> {
)
}
pragma[nomagic]
private string getTypeArgumentsQualifiedName(ConstructedGeneric cg, int i) {
result = getFullName(cg.getTypeArgument(i))
}
/** Gets the concatenation of the `getFullName` of type arguments. */
language[monotonicAggregates]
private string getTypeArgumentsQualifiedNames(ConstructedGeneric cg) {
result =
strictconcat(Type t, int i | t = cg.getTypeArgument(i) | getFullName(t), "," order by i)
strictconcat(int i |
exists(cg.getTypeArgument(i))
|
getTypeArgumentsQualifiedName(cg, i), "," order by i
)
}
/** Holds if declaration `d` has the qualified name `qualifier`.`name`. */

View File

@@ -195,8 +195,6 @@ predicate toGvn = toGvnCached/1;
/**
* Holds if the control flow elements `x` and `y` are structurally equal.
*/
pragma[inline]
predicate sameGvn(ControlFlowElement x, ControlFlowElement y) {
pragma[only_bind_into](toGvn(pragma[only_bind_out](x))) =
pragma[only_bind_into](toGvn(pragma[only_bind_out](y)))
}
bindingset[x, y]
pragma[inline_late]
predicate sameGvn(ControlFlowElement x, ControlFlowElement y) { toGvn(x) = toGvn(y) }

View File

@@ -1013,12 +1013,18 @@ module Internal {
* Holds if pre-basic-block `bb` only is reached when guard `g` has abstract value `v`,
* not taking implications into account.
*/
pragma[nomagic]
private predicate preControlsDirect(Guard g, PreBasicBlocks::PreBasicBlock bb, AbstractValue v) {
exists(PreBasicBlocks::ConditionBlock cb, ConditionalSuccessor s | cb.controls(bb, s) |
v.branch(cb.getLastElement(), s, g)
)
}
pragma[nomagic]
private predicate preControlsDefDirect(Guard g, PreSsa::Definition def, AbstractValue v) {
preControlsDirect(g, def.getBasicBlock(), v)
}
/** Holds if pre-basic-block `bb` only is reached when guard `g` has abstract value `v`. */
predicate preControls(Guard g, PreBasicBlocks::PreBasicBlock bb, AbstractValue v) {
preControlsDirect(g, bb, v)
@@ -1111,36 +1117,47 @@ module Internal {
)
}
pragma[noinline]
pragma[nomagic]
private predicate conditionalAssign0(
Guard guard, AbstractValue vGuard, PreSsa::PhiNode phi, Expr e, PreSsa::Definition upd,
PreBasicBlocks::PreBasicBlock bbGuard
PreBasicBlocks::PreBasicBlock bbGuard, PreBasicBlocks::PreBasicBlock bbPhi
) {
e = upd.getDefinition().getSource() and
upd = phi.getAnInput() and
preControlsDirect(guard, upd.getBasicBlock(), vGuard) and
preControlsDefDirect(guard, upd, vGuard) and
bbGuard.getAnElement() = guard and
bbGuard.strictlyDominates(phi.getBasicBlock()) and
not preControlsDirect(guard, phi.getBasicBlock(), vGuard)
bbPhi = phi.getBasicBlock()
}
pragma[noinline]
private predicate conditionalAssign1(
Guard guard, AbstractValue vGuard, PreSsa::PhiNode phi, Expr e, PreSsa::Definition upd,
PreBasicBlocks::PreBasicBlock bbGuard
) {
exists(PreBasicBlocks::PreBasicBlock bbPhi |
conditionalAssign0(guard, vGuard, phi, e, upd, bbGuard, bbPhi) and
bbGuard.strictlyDominates(bbPhi) and
not preControlsDefDirect(guard, phi, vGuard)
)
}
pragma[noinline]
private predicate conditionalAssign2(
Guard guard, AbstractValue vGuard, PreSsa::PhiNode phi, Expr e, PreSsa::Definition upd,
PreBasicBlocks::PreBasicBlock bbGuard, PreSsa::Definition other
) {
conditionalAssign0(guard, vGuard, phi, e, upd, bbGuard) and
conditionalAssign1(guard, vGuard, phi, e, upd, bbGuard) and
other != upd and
other = phi.getAnInput()
}
pragma[noinline]
private predicate conditionalAssign2(
private predicate conditionalAssign3(
Guard guard, AbstractValue vGuard, PreSsa::Definition def, Expr e, PreSsa::Definition upd,
PreBasicBlocks::PreBasicBlock bbGuard, PreSsa::Definition other
) {
conditionalAssign1(guard, vGuard, def, e, upd, bbGuard, other) and
preControlsDirect(guard, other.getBasicBlock(), vGuard.getDualValue())
conditionalAssign2(guard, vGuard, def, e, upd, bbGuard, other) and
preControlsDefDirect(guard, other, vGuard.getDualValue())
}
/** Gets the successor block that is reached when guard `g` has abstract value `v`. */
@@ -1153,11 +1170,11 @@ module Internal {
}
pragma[noinline]
private predicate conditionalAssign3(
private predicate conditionalAssign4(
Guard guard, AbstractValue vGuard, PreSsa::Definition def, Expr e, PreSsa::Definition upd,
PreBasicBlocks::PreBasicBlock bbGuard, PreSsa::Definition other
) {
conditionalAssign1(guard, vGuard, def, e, upd, bbGuard, other) and
conditionalAssign2(guard, vGuard, def, e, upd, bbGuard, other) and
other.getBasicBlock().dominates(bbGuard) and
not other.isLiveAtEndOfBlock(getConditionalSuccessor(guard, vGuard))
}
@@ -1184,10 +1201,10 @@ module Internal {
)
or
exists(PreSsa::Definition upd, PreBasicBlocks::PreBasicBlock bbGuard |
conditionalAssign0(guard, vGuard, def, e, upd, bbGuard)
conditionalAssign1(guard, vGuard, def, e, upd, bbGuard)
|
forall(PreSsa::Definition other |
conditionalAssign1(guard, vGuard, def, e, upd, bbGuard, other)
conditionalAssign2(guard, vGuard, def, e, upd, bbGuard, other)
|
// For example:
// if (guard)
@@ -1195,14 +1212,14 @@ module Internal {
// else
// other = b;
// def = phi(upd, other)
conditionalAssign2(guard, vGuard, def, e, upd, bbGuard, other)
conditionalAssign3(guard, vGuard, def, e, upd, bbGuard, other)
or
// For example:
// other = a;
// if (guard)
// upd = b;
// def = phi(other, upd)
conditionalAssign3(guard, vGuard, def, e, upd, bbGuard, other)
conditionalAssign4(guard, vGuard, def, e, upd, bbGuard, other)
)
)
}

View File

@@ -49,7 +49,10 @@ private newtype TCompletion =
nestedFinallyCompletion(outer, nestLevel)
}
pragma[noinline]
pragma[nomagic]
private int getAFinallyNestLevel() { result = any(Statements::TryStmtTree t).nestLevel() }
pragma[nomagic]
private predicate nestedFinallyCompletion(Completion outer, int nestLevel) {
(
outer = TReturnCompletion()
@@ -64,7 +67,7 @@ private predicate nestedFinallyCompletion(Completion outer, int nestLevel) {
or
outer = TExitCompletion()
) and
nestLevel = any(Statements::TryStmtTree t).nestLevel()
nestLevel = getAFinallyNestLevel()
}
pragma[noinline]

View File

@@ -75,8 +75,10 @@ class PreBasicBlock extends ControlFlowElement {
predicate immediatelyDominates(PreBasicBlock bb) { bbIDominates(this, bb) }
pragma[inline]
predicate strictlyDominates(PreBasicBlock bb) { this.immediatelyDominates+(bb) }
pragma[inline]
predicate dominates(PreBasicBlock bb) {
bb = this
or
@@ -97,6 +99,7 @@ class ConditionBlock extends PreBasicBlock {
)
}
pragma[nomagic]
private predicate immediatelyControls(PreBasicBlock succ, ConditionalCompletion cc) {
exists(ControlFlowElement last, Completion c |
last = this.getLastElement() and

View File

@@ -121,12 +121,19 @@ class OverridableCallable extends Callable, Overridable {
result = c.getDeclaringType()
}
pragma[nomagic]
private predicate isDeclaringSubType(ValueOrRefType t) {
t = this.getDeclaringType()
or
exists(ValueOrRefType mid | this.isDeclaringSubType(mid) | t = mid.getASubType())
}
pragma[nomagic]
private predicate isDeclaringSubType(ValueOrRefType t, ValueOrRefType sub) {
this.isDeclaringSubType(t) and
t = sub.getABaseType()
}
pragma[noinline]
private Callable getAnOverrider0(ValueOrRefType t) {
// A (transitive) overrider
@@ -155,10 +162,7 @@ class OverridableCallable extends Callable, Overridable {
Callable getAnOverrider(ValueOrRefType t) {
result = this.getAnOverrider0(t)
or
exists(ValueOrRefType mid | result = this.getAnOverrider(mid) |
t = mid.getABaseType() and
this.isDeclaringSubType(t)
)
exists(ValueOrRefType mid | result = this.getAnOverrider(mid) | this.isDeclaringSubType(t, mid))
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,12 @@ import csharp
import semmle.code.csharp.security.dataflow.UnsafeDeserializationQuery
import Flow::PathGraph
bindingset[e1, e2]
pragma[inline_late]
private predicate sameParent(DataFlow::Node e1, DataFlow::Node e2) {
e1.asExpr().getParent() = e2.asExpr().getParent()
}
module Flow =
DataFlow::MergePathGraph3<TaintToObjectMethodTracking::PathNode,
TaintToConstructorOrStaticMethodTracking::PathNode, JsonConvertTracking::PathNode,
@@ -48,7 +54,7 @@ where
exists(DataFlow::Node settingsCallArg |
JsonConvertTracking::flowPath(userInput.asPathNode3(), deserializeCallArg.asPathNode3()) and
TypeNameTracking::flow(_, settingsCallArg) and
deserializeCallArg.getNode().asExpr().getParent() = settingsCallArg.asExpr().getParent()
sameParent(deserializeCallArg.getNode(), settingsCallArg)
)
select deserializeCallArg, userInput, deserializeCallArg, "$@ flows to unsafe deserializer.",
userInput, "User-provided data"