From d14ee931e1fb41e606fa576bf83c1e9e51da651b Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 18 Apr 2023 19:19:59 +0100 Subject: [PATCH] C++: IR translation for non-runtime-initialized static local variables. --- .../internal/IRFunctionBase.qll | 2 +- .../raw/internal/IRConstruction.qll | 13 +++++++--- .../raw/internal/TranslatedElement.qll | 26 ++++++++++--------- .../raw/internal/TranslatedFunction.qll | 2 ++ .../raw/internal/TranslatedGlobalVar.qll | 16 ++++++------ .../raw/internal/TranslatedInitialization.qll | 5 +++- .../code/cpp/ir/internal/IRCppLanguage.qll | 2 +- .../cpp/ir/internal/IRCppLanguageDebug.qll | 8 +++++- .../test/library-tests/ir/ir/PrintConfig.qll | 2 ++ .../internal/IRFunctionBase.qll | 2 +- 10 files changed, 50 insertions(+), 28 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll index 576b4f9adf1..571b0a12f49 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll @@ -6,7 +6,7 @@ private import IRFunctionBaseInternal private newtype TIRFunction = TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or - TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) } + TVarInitIRFunction(Language::Variable var) { IRConstruction::Raw::varHasIRFunc(var) } /** * The IR for a function. This base class contains only the predicates that are the same between all diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 2c674e11626..8b3e90547e0 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -37,7 +37,13 @@ module Raw { predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) } cached - predicate varHasIRFunc(GlobalOrNamespaceVariable var) { + predicate varHasIRFunc(Variable var) { + ( + var instanceof GlobalOrNamespaceVariable + or + not var.isFromUninstantiatedTemplate(_) and + var instanceof StaticInitializedStaticLocalVariable + ) and var.hasInitializer() and ( not var.getType().isDeeplyConst() @@ -75,9 +81,10 @@ module Raw { } cached - predicate hasDynamicInitializationFlag(Function func, StaticLocalVariable var, CppType type) { + predicate hasDynamicInitializationFlag( + Function func, RuntimeInitializedStaticLocalVariable var, CppType type + ) { var.getFunction() = func and - var.hasDynamicInitialization() and type = getBoolType() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index c92fd197db1..f6fc0ea8960 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -62,15 +62,6 @@ private predicate ignoreExprAndDescendants(Expr expr) { // constant value. isIRConstant(getRealParent(expr)) or - // Only translate the initializer of a static local if it uses run-time data. - // Otherwise the initializer does not run in function scope. - exists(Initializer init, StaticStorageDurationVariable var | - init = var.getInitializer() and - not var.hasDynamicInitialization() and - expr = init.getExpr().getFullyConverted() and - not var instanceof GlobalOrNamespaceVariable - ) - or // Ignore descendants of `__assume` expressions, since we translated these to `NoOp`. getRealParent(expr) instanceof AssumeExpr or @@ -438,6 +429,17 @@ predicate hasTranslatedSyntheticTemporaryObject(Expr expr) { not expr.hasLValueToRValueConversion() } +class StaticInitializedStaticLocalVariable extends StaticLocalVariable { + StaticInitializedStaticLocalVariable() { + this.hasInitializer() and + not this.hasDynamicInitialization() + } +} + +class RuntimeInitializedStaticLocalVariable extends StaticLocalVariable { + RuntimeInitializedStaticLocalVariable() { this.hasDynamicInitialization() } +} + /** * Holds if the specified `DeclarationEntry` needs an IR translation. An IR translation is only * necessary for automatic local variables, or for static local variables with dynamic @@ -453,7 +455,7 @@ private predicate translateDeclarationEntry(IRDeclarationEntry entry) { not var.isStatic() or // Ignore static variables unless they have a dynamic initializer. - var.(StaticLocalVariable).hasDynamicInitialization() + var instanceof RuntimeInitializedStaticLocalVariable ) ) } @@ -755,7 +757,7 @@ newtype TTranslatedElement = } or // The side effect that initializes newly-allocated memory. TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or - TTranslatedGlobalOrNamespaceVarInit(GlobalOrNamespaceVariable var) { Raw::varHasIRFunc(var) } + TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) } /** * Gets the index of the first explicitly initialized element in `initList` @@ -1043,6 +1045,6 @@ abstract class TranslatedRootElement extends TranslatedElement { TranslatedRootElement() { this instanceof TTranslatedFunction or - this instanceof TTranslatedGlobalOrNamespaceVarInit + this instanceof TTranslatedStaticStorageDurationVarInit } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index d29d8c80cf5..c5fc89325e2 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -322,6 +322,8 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction { ( var instanceof GlobalOrNamespaceVariable or + var instanceof StaticLocalVariable + or var instanceof MemberVariable and not var instanceof Field ) and exists(VariableAccess access | diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll index 5a4f7977ac8..cfbd78fbdc5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll @@ -8,16 +8,16 @@ private import TranslatedInitialization private import InstructionTag private import semmle.code.cpp.ir.internal.IRUtilities -class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement, - TTranslatedGlobalOrNamespaceVarInit, InitializationContext +class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement, + TTranslatedStaticStorageDurationVarInit, InitializationContext { - GlobalOrNamespaceVariable var; + Variable var; - TranslatedGlobalOrNamespaceVarInit() { this = TTranslatedGlobalOrNamespaceVarInit(var) } + TranslatedStaticStorageDurationVarInit() { this = TTranslatedStaticStorageDurationVarInit(var) } override string toString() { result = var.toString() } - final override GlobalOrNamespaceVariable getAst() { result = var } + final override Variable getAst() { result = var } final override Declaration getFunction() { result = var } @@ -111,6 +111,8 @@ class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement, ( varUsed instanceof GlobalOrNamespaceVariable or + varUsed instanceof StaticLocalVariable + or varUsed instanceof MemberVariable and not varUsed instanceof Field ) and exists(VariableAccess access | @@ -128,6 +130,4 @@ class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement, } } -TranslatedGlobalOrNamespaceVarInit getTranslatedVarInit(GlobalOrNamespaceVariable var) { - result.getAst() = var -} +TranslatedStaticStorageDurationVarInit getTranslatedVarInit(Variable var) { result.getAst() = var } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 5e50c834d67..fe6b20cbd8d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -139,7 +139,8 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn final override Declaration getFunction() { result = expr.getEnclosingFunction() or - result = expr.getEnclosingVariable().(GlobalOrNamespaceVariable) + result = expr.getEnclosingVariable().(GlobalOrNamespaceVariable) or + result = expr.getEnclosingVariable().(StaticInitializedStaticLocalVariable) } final override Locatable getAst() { result = expr } @@ -654,6 +655,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement { result = initList.getEnclosingFunction() or result = initList.getEnclosingVariable().(GlobalOrNamespaceVariable) + or + result = initList.getEnclosingVariable().(StaticInitializedStaticLocalVariable) } final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll index 6e6c632ae3d..681e2838ffb 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll @@ -47,7 +47,7 @@ class Variable = Cpp::Variable; class AutomaticVariable = Cpp::StackVariable; -class StaticVariable = Cpp::Variable; +class StaticVariable = Cpp::StaticStorageDurationVariable; class GlobalVariable = Cpp::GlobalOrNamespaceVariable; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguageDebug.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguageDebug.qll index 9c90adfb54b..33ce23134fc 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguageDebug.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguageDebug.qll @@ -1,3 +1,9 @@ +private import cpp private import semmle.code.cpp.Print as Print -predicate getIdentityString = Print::getIdentityString/1; +string getIdentityString(Declaration decl) { + if decl instanceof StaticLocalVariable + then + exists(StaticLocalVariable v | v = decl | result = v.getType().toString() + " " + v.getName()) + else result = Print::getIdentityString(decl) +} diff --git a/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll b/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll index bd77d831cb7..6d3db164900 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll +++ b/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll @@ -18,5 +18,7 @@ predicate shouldDumpFunction(Declaration decl) { decl instanceof Function or decl.(GlobalOrNamespaceVariable).hasInitializer() + or + decl.(StaticLocalVariable).hasInitializer() ) } diff --git a/csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll b/csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll index 576b4f9adf1..571b0a12f49 100644 --- a/csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll +++ b/csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll @@ -6,7 +6,7 @@ private import IRFunctionBaseInternal private newtype TIRFunction = TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or - TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) } + TVarInitIRFunction(Language::Variable var) { IRConstruction::Raw::varHasIRFunc(var) } /** * The IR for a function. This base class contains only the predicates that are the same between all