C++: Use StackVariable, remove not v.isStatic()

In these files it was possible to remove calls to `isStatic` by
switching from `LocalScopeVariable` to `StackVariable`. This changes
semantics, hopefully for the better, to treat `thread_local` locals the
same as `static` locals.
This commit is contained in:
Jonas Jensen
2019-11-18 20:08:59 +01:00
parent e57f98ca64
commit 29f66ff095
10 changed files with 33 additions and 53 deletions

View File

@@ -20,11 +20,10 @@ class ReturnPointsToExpr extends PointsToExpr {
ReturnStmt getReturnStmt() { result.getExpr().getFullyConverted() = this } ReturnStmt getReturnStmt() { result.getExpr().getFullyConverted() = this }
} }
from ReturnPointsToExpr ret, LocalVariable local, float confidence from ReturnPointsToExpr ret, StackVariable local, float confidence
where where
ret.pointsTo() = local and ret.pointsTo() = local and
ret.getReturnStmt().getEnclosingFunction() = local.getFunction() and ret.getReturnStmt().getEnclosingFunction() = local.getFunction() and
not local.isStatic() and
confidence = ret.confidence() and confidence = ret.confidence() and
confidence > 0.01 confidence > 0.01
select ret, select ret,

View File

@@ -20,11 +20,10 @@ class ScopeUtilityClass extends Class {
Call getAUse() { result = this.getAConstructor().getACallToThisFunction() } Call getAUse() { result = this.getAConstructor().getACallToThisFunction() }
} }
from LocalScopeVariable v, ControlFlowNode def from StackVariable v, ControlFlowNode def
where where
definition(v, def) and definition(v, def) and
not definitionUsePair(v, def, _) and not definitionUsePair(v, def, _) and
not v.isStatic() and
not v.getAnAccess().isAddressOfAccess() and not v.getAnAccess().isAddressOfAccess() and
// parameter initializers are not in the call-graph at the moment // parameter initializers are not in the call-graph at the moment
not v.(Parameter).getInitializer().getExpr() = def and not v.(Parameter).getInitializer().getExpr() = def and

View File

@@ -42,10 +42,8 @@ predicate hasNontrivialConversion(Expr e) {
hasNontrivialConversion(e.getConversion()) hasNontrivialConversion(e.getConversion())
} }
from LocalScopeVariable var, VariableAccess va, ReturnStmt r from StackVariable var, VariableAccess va, ReturnStmt r
where where
not var.isStatic() and
not var.isThreadLocal() and
not var.getUnspecifiedType() instanceof ReferenceType and not var.getUnspecifiedType() instanceof ReferenceType and
not r.isFromUninstantiatedTemplate(_) and not r.isFromUninstantiatedTemplate(_) and
va = var.getAnAccess() and va = var.getAnAccess() and

View File

@@ -12,7 +12,7 @@
*/ */
import cpp import cpp
import semmle.code.cpp.controlflow.LocalScopeVariableReachability import semmle.code.cpp.controlflow.StackVariableReachability
/** /**
* Auxiliary predicate: Types that don't require initialization * Auxiliary predicate: Types that don't require initialization
@@ -40,23 +40,17 @@ DeclStmt declWithNoInit(LocalVariable v) {
result.getADeclaration() = v and result.getADeclaration() = v and
not exists(v.getInitializer()) and not exists(v.getInitializer()) and
/* The type of the variable is not stack-allocated. */ /* The type of the variable is not stack-allocated. */
not allocatedType(v.getType()) and not allocatedType(v.getType())
/* The variable is not static (otherwise it is zeroed). */
not v.isStatic() and
/* The variable is not extern (otherwise it is zeroed). */
not v.hasSpecifier("extern")
} }
class UninitialisedLocalReachability extends LocalScopeVariableReachability { class UninitialisedLocalReachability extends StackVariableReachability {
UninitialisedLocalReachability() { this = "UninitialisedLocal" } UninitialisedLocalReachability() { this = "UninitialisedLocal" }
override predicate isSource(ControlFlowNode node, LocalScopeVariable v) { override predicate isSource(ControlFlowNode node, StackVariable v) { node = declWithNoInit(v) }
node = declWithNoInit(v)
}
override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { useOfVarActual(v, node) } override predicate isSink(ControlFlowNode node, StackVariable v) { useOfVarActual(v, node) }
override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) { override predicate isBarrier(ControlFlowNode node, StackVariable v) {
// only report the _first_ possibly uninitialized use // only report the _first_ possibly uninitialized use
useOfVarActual(v, node) or useOfVarActual(v, node) or
definitionBarrier(v, node) definitionBarrier(v, node)

View File

@@ -20,10 +20,9 @@ class ReturnPointsToExpr extends PointsToExpr {
ReturnStmt getReturnStmt() { result.getExpr() = this } ReturnStmt getReturnStmt() { result.getExpr() = this }
} }
from ReturnPointsToExpr ret, LocalVariable dest from ReturnPointsToExpr ret, StackVariable dest
where where
ret.pointsTo() = dest and ret.pointsTo() = dest and
ret.getReturnStmt().getParentStmt().getEnclosingFunction() = dest.getFunction() and ret.getReturnStmt().getParentStmt().getEnclosingFunction() = dest.getFunction()
not dest.isStatic()
select ret.getReturnStmt(), select ret.getReturnStmt(),
"AV Rule 111: A function shall not return a pointer or reference to a non-static local object." "AV Rule 111: A function shall not return a pointer or reference to a non-static local object."

View File

@@ -61,7 +61,7 @@ predicate stackPointerFlowsToUse(Expr use, Type useType, Expr source, boolean is
stackPointerFlowsToUse(use.(PointerAddExpr).getAnOperand(), useType, source, isLocal) stackPointerFlowsToUse(use.(PointerAddExpr).getAnOperand(), useType, source, isLocal)
or or
// Indirect use of a stack address. // Indirect use of a stack address.
exists(SsaDefinition def, LocalScopeVariable var | exists(SsaDefinition def, StackVariable var |
stackPointerFlowsToDef(def, var, useType, source, isLocal) and stackPointerFlowsToDef(def, var, useType, source, isLocal) and
use = def.getAUse(var) use = def.getAUse(var)
) )
@@ -97,8 +97,7 @@ private PointerType getExprPtrType(Expr use) { result = use.getUnspecifiedType()
predicate stackReferenceFlowsToUse(Expr use, Type useType, Expr source, boolean isLocal) { predicate stackReferenceFlowsToUse(Expr use, Type useType, Expr source, boolean isLocal) {
// Stack variables // Stack variables
exists(LocalScopeVariable var | exists(StackVariable var |
not var.isStatic() and
use = source and use = source and
source = var.getAnAccess() and source = var.getAnAccess() and
isLocal = true and isLocal = true and
@@ -140,7 +139,7 @@ predicate stackReferenceFlowsToUse(Expr use, Type useType, Expr source, boolean
stackPointerFlowsToUse(use.(PointerDereferenceExpr).getOperand(), useType, source, isLocal) stackPointerFlowsToUse(use.(PointerDereferenceExpr).getOperand(), useType, source, isLocal)
or or
// Indirect use of a stack reference, via a reference variable. // Indirect use of a stack reference, via a reference variable.
exists(SsaDefinition def, LocalScopeVariable var | exists(SsaDefinition def, StackVariable var |
stackReferenceFlowsToDef(def, var, useType, source, isLocal) and stackReferenceFlowsToDef(def, var, useType, source, isLocal) and
use = def.getAUse(var) use = def.getAUse(var)
) )
@@ -162,7 +161,7 @@ predicate stackReferenceFlowsToUse(Expr use, Type useType, Expr source, boolean
* addresses through SSA definitions. * addresses through SSA definitions.
*/ */
predicate stackPointerFlowsToDef( predicate stackPointerFlowsToDef(
SsaDefinition def, LocalScopeVariable var, Type useType, Expr source, boolean isLocal SsaDefinition def, StackVariable var, Type useType, Expr source, boolean isLocal
) { ) {
stackPointerFlowsToUse(def.getDefiningValue(var), useType, source, isLocal) stackPointerFlowsToUse(def.getDefiningValue(var), useType, source, isLocal)
or or
@@ -184,7 +183,7 @@ predicate stackPointerFlowsToDef(
* int&, rather than pointers. * int&, rather than pointers.
*/ */
predicate stackReferenceFlowsToDef( predicate stackReferenceFlowsToDef(
SsaDefinition def, LocalScopeVariable var, Type useType, Expr source, boolean isLocal SsaDefinition def, StackVariable var, Type useType, Expr source, boolean isLocal
) { ) {
// Check that the type of the variable is a reference type and delegate // Check that the type of the variable is a reference type and delegate
// the rest of the work to stackReferenceFlowsToDef_Impl. // the rest of the work to stackReferenceFlowsToDef_Impl.
@@ -197,7 +196,7 @@ predicate stackReferenceFlowsToDef(
* predicate. * predicate.
*/ */
predicate stackReferenceFlowsToDef_Impl( predicate stackReferenceFlowsToDef_Impl(
SsaDefinition def, LocalScopeVariable var, Type useType, Expr source, boolean isLocal SsaDefinition def, StackVariable var, Type useType, Expr source, boolean isLocal
) { ) {
stackReferenceFlowsToUse(def.getDefiningValue(var), useType, source, isLocal) stackReferenceFlowsToUse(def.getDefiningValue(var), useType, source, isLocal)
or or
@@ -213,7 +212,7 @@ predicate stackReferenceFlowsToDef_Impl(
} }
/** The type of the variable is a reference type, such as int&. */ /** The type of the variable is a reference type, such as int&. */
predicate isReferenceVariable(LocalScopeVariable var) { predicate isReferenceVariable(StackVariable var) {
var.getUnspecifiedType() instanceof ReferenceType var.getUnspecifiedType() instanceof ReferenceType
} }
@@ -284,7 +283,7 @@ predicate memberFcnMightRunOnStack(MemberFunction fcn, Type useType) {
predicate constructorMightRunOnStack(Constructor constructor) { predicate constructorMightRunOnStack(Constructor constructor) {
exists(ConstructorCall call | call.getTarget() = constructor | exists(ConstructorCall call | call.getTarget() = constructor |
// Call to a constructor from a stack variable's initializer. // Call to a constructor from a stack variable's initializer.
exists(LocalScopeVariable var | var.getInitializer().getExpr() = call) exists(StackVariable var | var.getInitializer().getExpr() = call)
or or
// Call to a constructor from another constructor which might // Call to a constructor from another constructor which might
// also run on the stack. // also run on the stack.

View File

@@ -88,7 +88,7 @@ class FlowVar extends TFlowVar {
* `FlowVar` instance for the uninitialized value of that variable. * `FlowVar` instance for the uninitialized value of that variable.
*/ */
cached cached
abstract predicate definedByInitialValue(LocalScopeVariable v); abstract predicate definedByInitialValue(StackVariable v);
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
cached cached
@@ -269,7 +269,7 @@ module FlowVar_internal {
* Holds if `sbb` is the `SubBasicBlock` where `v` receives its initial value. * Holds if `sbb` is the `SubBasicBlock` where `v` receives its initial value.
* See the documentation for `FlowVar.definedByInitialValue`. * See the documentation for `FlowVar.definedByInitialValue`.
*/ */
predicate blockVarDefinedByVariable(SubBasicBlock sbb, LocalScopeVariable v) { predicate blockVarDefinedByVariable(SubBasicBlock sbb, StackVariable v) {
sbb = v.(Parameter).getFunction().getEntryPoint() sbb = v.(Parameter).getFunction().getEntryPoint()
or or
exists(DeclStmt declStmt | exists(DeclStmt declStmt |
@@ -280,7 +280,7 @@ module FlowVar_internal {
} }
newtype TFlowVar = newtype TFlowVar =
TSsaVar(SsaDefinition def, LocalScopeVariable v) { TSsaVar(SsaDefinition def, StackVariable v) {
fullySupportedSsaVariable(v) and fullySupportedSsaVariable(v) and
v = def.getAVariable() v = def.getAVariable()
} or } or
@@ -304,7 +304,7 @@ module FlowVar_internal {
*/ */
class SsaVar extends TSsaVar, FlowVar { class SsaVar extends TSsaVar, FlowVar {
SsaDefinition def; SsaDefinition def;
LocalScopeVariable v; StackVariable v;
SsaVar() { this = TSsaVar(def, v) } SsaVar() { this = TSsaVar(def, v) }
@@ -344,7 +344,7 @@ module FlowVar_internal {
override predicate definedPartiallyAt(Expr e) { none() } override predicate definedPartiallyAt(Expr e) { none() }
override predicate definedByInitialValue(LocalScopeVariable param) { override predicate definedByInitialValue(StackVariable param) {
def.definedByParameter(param) and def.definedByParameter(param) and
param = v param = v
} }
@@ -408,7 +408,7 @@ module FlowVar_internal {
getAReachedBlockVarSBB(this).getANode() = p.getFunction() getAReachedBlockVarSBB(this).getANode() = p.getFunction()
} }
override predicate definedByInitialValue(LocalScopeVariable lsv) { override predicate definedByInitialValue(StackVariable lsv) {
blockVarDefinedByVariable(sbb, lsv) and blockVarDefinedByVariable(sbb, lsv) and
lsv = v lsv = v
} }
@@ -648,11 +648,8 @@ module FlowVar_internal {
/** /**
* A local variable that is uninitialized immediately after its declaration. * A local variable that is uninitialized immediately after its declaration.
*/ */
class UninitializedLocalVariable extends LocalVariable { class UninitializedLocalVariable extends LocalVariable, StackVariable {
UninitializedLocalVariable() { UninitializedLocalVariable() { not this.hasInitializer() }
not this.hasInitializer() and
not this.isStatic()
}
} }
/** Holds if `va` may be an uninitialized access to `v`. */ /** Holds if `va` may be an uninitialized access to `v`. */

View File

@@ -62,11 +62,10 @@ abstract class CrementOperation extends UnaryArithmeticOperation {
override predicate mayBeImpure() { any() } override predicate mayBeImpure() { any() }
override predicate mayBeGloballyImpure() { override predicate mayBeGloballyImpure() {
not exists(VariableAccess va, LocalScopeVariable v | not exists(VariableAccess va, StackVariable v |
va = this.getOperand() and va = this.getOperand() and
v = va.getTarget() and v = va.getTarget() and
not va.getConversion+() instanceof ReferenceDereferenceExpr and not va.getConversion+() instanceof ReferenceDereferenceExpr
not v.isStatic()
) )
} }
} }

View File

@@ -21,11 +21,10 @@ abstract class Assignment extends Operation {
override predicate mayBeGloballyImpure() { override predicate mayBeGloballyImpure() {
this.getRValue().mayBeGloballyImpure() this.getRValue().mayBeGloballyImpure()
or or
not exists(VariableAccess va, LocalScopeVariable v | not exists(VariableAccess va, StackVariable v |
va = this.getLValue() and va = this.getLValue() and
v = va.getTarget() and v = va.getTarget() and
not va.getConversion+() instanceof ReferenceDereferenceExpr and not va.getConversion+() instanceof ReferenceDereferenceExpr
not v.isStatic()
) )
} }
} }

View File

@@ -32,7 +32,7 @@ class StringLiteral = Cpp::StringLiteral;
class Variable = Cpp::Variable; class Variable = Cpp::Variable;
class AutomaticVariable = Cpp::LocalScopeVariable; class AutomaticVariable = Cpp::StackVariable;
class StaticVariable = Cpp::Variable; class StaticVariable = Cpp::Variable;
@@ -66,10 +66,7 @@ int getTypeSize(Type type) { result = type.getSize() }
int getPointerSize() { exists(Cpp::NullPointerType nullptr | result = nullptr.getSize()) } int getPointerSize() { exists(Cpp::NullPointerType nullptr | result = nullptr.getSize()) }
predicate isVariableAutomatic(Variable var) { predicate isVariableAutomatic(Cpp::StackVariable var) { any() }
var instanceof Cpp::LocalScopeVariable and
not var.(Cpp::LocalScopeVariable).isStatic()
}
string getStringLiteralText(StringLiteral s) { string getStringLiteralText(StringLiteral s) {
result = s.getValueText().replaceAll("\n", " ").replaceAll("\r", "").replaceAll("\t", " ") result = s.getValueText().replaceAll("\n", " ").replaceAll("\r", "").replaceAll("\t", " ")