mirror of
https://github.com/github/codeql.git
synced 2025-12-23 12:16:33 +01:00
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:
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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."
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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`. */
|
||||||
|
|||||||
@@ -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()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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", " ")
|
||||||
|
|||||||
Reference in New Issue
Block a user