From de05aee483c204aa6da50fe6213c44c229748348 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 18 Nov 2024 11:11:25 -0500 Subject: [PATCH 01/11] Adding model transition to using Throwing.qll. --- .../raw/internal/TranslatedCall.qll | 4 +- .../cpp/models/implementations/Memcpy.qll | 4 +- .../cpp/models/implementations/Memset.qll | 4 +- .../implementations/NoexceptFunction.qll | 4 +- .../cpp/models/implementations/Printf.qll | 12 +++- .../cpp/models/implementations/Strcat.qll | 4 +- .../cpp/models/implementations/Strcpy.qll | 4 +- .../StructuredExceptionHandling.qll | 23 ++++++- .../cpp/models/interfaces/NonThrowing.qll | 11 --- .../code/cpp/models/interfaces/Throwing.qll | 69 +++++++++++++++++-- 10 files changed, 112 insertions(+), 27 deletions(-) delete mode 100644 cpp/ql/lib/semmle/code/cpp/models/interfaces/NonThrowing.qll diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index daa6bdaafcf6..a4c678869590 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -363,11 +363,11 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { } final override predicate mayThrowException() { - expr.getTarget().(ThrowingFunction).mayThrowException(_) + expr.getTarget().(ThrowingFunction).mayRaiseException() } final override predicate mustThrowException() { - expr.getTarget().(ThrowingFunction).mayThrowException(true) + expr.getTarget().(ThrowingFunction).alwaysRaisesException() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll index 0bf2dd31fe40..8c3ae368da9d 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll @@ -9,7 +9,7 @@ import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.SideEffect import semmle.code.cpp.models.interfaces.Taint -import semmle.code.cpp.models.interfaces.NonThrowing +import semmle.code.cpp.models.interfaces.Throwing /** * The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant @@ -106,6 +106,8 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect not this.hasGlobalName(["bcopy", mempcpy(), "memccpy"]) and index = this.getParamDest() } + + override TCxxException getExceptionType() { any() } } private string mempcpy() { result = ["mempcpy", "wmempcpy"] } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll index ab2e0af99f38..6a4ab8a133f2 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.SideEffect -import semmle.code.cpp.models.interfaces.NonThrowing +import semmle.code.cpp.models.interfaces.Throwing private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, AliasFunction, SideEffectFunction, NonThrowingFunction @@ -74,6 +74,8 @@ private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, Alias i = 0 and if this.hasGlobalName(bzero()) then result = 1 else result = 2 } + + override TCxxException getExceptionType() { any() } } private string bzero() { result = ["bzero", "explicit_bzero"] } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/NoexceptFunction.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/NoexceptFunction.qll index b0f76ee6538a..ee05b2a68a0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/NoexceptFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/NoexceptFunction.qll @@ -1,4 +1,4 @@ -import semmle.code.cpp.models.interfaces.NonThrowing +import semmle.code.cpp.models.interfaces.Throwing /** * A function that is annotated with a `noexcept` specifier (or the equivalent @@ -8,4 +8,6 @@ import semmle.code.cpp.models.interfaces.NonThrowing */ class NoexceptFunction extends NonThrowingFunction { NoexceptFunction() { this.isNoExcept() or this.isNoThrow() } + + override TCxxException getExceptionType() { any() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll index 9c3bfb4f35ec..7dbd38126bf6 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.models.interfaces.FormattingFunction import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.SideEffect -import semmle.code.cpp.models.interfaces.NonThrowing +import semmle.code.cpp.models.interfaces.Throwing /** * The standard functions `printf`, `wprintf` and their glib variants. @@ -32,6 +32,8 @@ private class Printf extends FormattingFunction, AliasFunction, NonThrowingFunct override predicate parameterEscapesOnlyViaReturn(int n) { none() } override predicate parameterIsAlwaysReturned(int n) { none() } + + override TCxxException getExceptionType() { any() } } /** @@ -50,6 +52,8 @@ private class Fprintf extends FormattingFunction, NonThrowingFunction { override int getFormatParameterIndex() { result = 1 } override int getOutputParameterIndex(boolean isStream) { result = 0 and isStream = true } + + override TCxxException getExceptionType() { any() } } /** @@ -93,6 +97,8 @@ private class Sprintf extends FormattingFunction, NonThrowingFunction { then result = 4 else result = super.getFirstFormatArgumentIndex() } + + override TCxxException getExceptionType() { any() } } /** @@ -165,6 +171,8 @@ private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction, // We don't know how many parameters are passed to the function since it's varargs, but they also have read side effects. i = this.getFormatParameterIndex() and buffer = true } + + override TCxxException getExceptionType() { any() } } /** @@ -215,4 +223,6 @@ private class Syslog extends FormattingFunction, NonThrowingFunction { override int getFormatParameterIndex() { result = 1 } override predicate isOutputGlobal() { any() } + + override TCxxException getExceptionType() { any() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll index 9b11ed0af153..df85c56148a8 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll @@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.SideEffect -import semmle.code.cpp.models.interfaces.NonThrowing +import semmle.code.cpp.models.interfaces.Throwing /** * The standard function `strcat` and its wide, sized, and Microsoft variants. @@ -94,6 +94,8 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid (i = 0 or i = 1) and buffer = true } + + override TCxxException getExceptionType() { any() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll index b7f06f0cebf4..b09cbeb8dc60 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll @@ -7,7 +7,7 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.SideEffect -import semmle.code.cpp.models.interfaces.NonThrowing +import semmle.code.cpp.models.interfaces.Throwing /** * The standard function `strcpy` and its wide, sized, and Microsoft variants. @@ -145,4 +145,6 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid i = this.getParamDest() and result = this.getParamSize() } + + override TCxxException getExceptionType() { any() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll index af8f3088f255..d5941488d0d7 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll @@ -1,9 +1,26 @@ import semmle.code.cpp.models.interfaces.Throwing -class WindowsDriverFunction extends ThrowingFunction { - WindowsDriverFunction() { +/** + * The default behavior for Structured Exception Handling (SEH) is + * any function may (conditionally) raise an exception. + * NOTE: this can be overridden by for any specific function to make in + * unconditional or non-throwing. IR generation will enforce + * the most strict interpretation. + */ +class DefaultSehExceptionBehavior extends ThrowingFunction { + DefaultSehExceptionBehavior() { any() } + + override predicate raisesException(boolean unconditional) { unconditional = false } + + override TSehException getExceptionType() { any() } +} + +class WindowsDriverExceptionAnnotation extends ThrowingFunction { + WindowsDriverExceptionAnnotation() { this.hasGlobalName(["RaiseException", "ExRaiseAccessViolation", "ExRaiseDatatypeMisalignment"]) } - final override predicate mayThrowException(boolean unconditional) { unconditional = true } + override predicate raisesException(boolean unconditional) { unconditional = true } + + override TSehException getExceptionType() { any() } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/NonThrowing.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/NonThrowing.qll deleted file mode 100644 index 64901d39ad30..000000000000 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/NonThrowing.qll +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Provides an abstract class for modeling functions that never throw. - */ - -import semmle.code.cpp.Function -import semmle.code.cpp.models.Models - -/** - * A function that is guaranteed to never throw. - */ -abstract class NonThrowingFunction extends Function { } diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll index 79b7523f1d9f..72db8c9e96c7 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll @@ -11,12 +11,71 @@ import semmle.code.cpp.models.Models import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs /** - * A class that models the exceptional behavior of a function. + * Represents a type of exception, + * either Structured Exception Handling (SEH) or C++ exceptions. */ -abstract class ThrowingFunction extends Function { +newtype TException = + /** Structured Exception Handling (SEH) exception */ + TSehException() or + /** C++ exception */ + TCxxException() + +/** + * Functions with information about how an exception is thrown or if one is thrown at all. + * If throwing details conflict for the same function, IR is assumed + * to use the most restricted interpretation, meaning taking options + * that stipulate no exception is raised, before the exception is always raised, + * before conditional exceptions. + * + * Annotations must specify if the exception is from SEH (structured exception handling) + * or ordinary c++ exceptions. + */ +abstract private class ExceptionAnnotation extends Function { + /** + * Returns the type of exception this annotation is for, + * either a CPP exception or a STructured Exception Handling (SEH) exception. + */ + abstract TException getExceptionType(); + + /** + * Holds if the exception type of this annotation is for a Structured Exception Handling (SEH) exception. + */ + final predicate isSeh() { this.getExceptionType() = TSehException() } + + /** + * Holds if the exception type of this annotation is for a CPP exception. + */ + final predicate isCxx() { this.getExceptionType() = TCxxException() } +} + +/** + * A Function that is known to not throw an exception. + */ +abstract class NonThrowingFunction extends ExceptionAnnotation { } + +/** + * A function this is known to raise an exception. + */ +abstract class ThrowingFunction extends ExceptionAnnotation { + ThrowingFunction() { any() } + + /** + * Holds if this function may raise an exception during evaluation. + * If `unconditional` is `false` the function may raise, and if `true` the function + * will always raise an exception. + * Do not specify `none()` if no exception is raised, instead use the + * `NonThrowingFunction` class instead. + */ + abstract predicate raisesException(boolean unconditional); + + /** + * Holds if this function will always raise an exception if called + */ + final predicate alwaysRaisesException() { this.raisesException(true) } + /** - * Holds if this function may throw an exception during evaluation. - * If `unconditional` is `true` the function always throws an exception. + * Holds if this function may raise an exception if called but + * it is not guaranteed to do so. I.e., the function does not always raise an exception. */ - abstract predicate mayThrowException(boolean unconditional); + final predicate mayRaiseException() { this.raisesException(false) } } From 4b83a451bd0547bba0d6bd41750d4739fd7dd5e0 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 18 Nov 2024 11:14:46 -0500 Subject: [PATCH 02/11] Change log --- cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md diff --git a/cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md b/cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md new file mode 100644 index 000000000000..f3c33f40b517 --- /dev/null +++ b/cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Removed NonThrowing.qll. Throwing meta-data now part of Throwing.qll. Updated models and IR to use the new Throwing library and predicates. \ No newline at end of file From 792231c949154be6b003d86204df40478e23e600 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Mon, 18 Nov 2024 14:43:44 -0500 Subject: [PATCH 03/11] Removing SEH default case for function calls as the logic to handle SEH is not yet part of the IR generation to make this logic work. --- .../StructuredExceptionHandling.qll | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll index d5941488d0d7..485dc7137b81 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll @@ -1,20 +1,5 @@ import semmle.code.cpp.models.interfaces.Throwing -/** - * The default behavior for Structured Exception Handling (SEH) is - * any function may (conditionally) raise an exception. - * NOTE: this can be overridden by for any specific function to make in - * unconditional or non-throwing. IR generation will enforce - * the most strict interpretation. - */ -class DefaultSehExceptionBehavior extends ThrowingFunction { - DefaultSehExceptionBehavior() { any() } - - override predicate raisesException(boolean unconditional) { unconditional = false } - - override TSehException getExceptionType() { any() } -} - class WindowsDriverExceptionAnnotation extends ThrowingFunction { WindowsDriverExceptionAnnotation() { this.hasGlobalName(["RaiseException", "ExRaiseAccessViolation", "ExRaiseDatatypeMisalignment"]) From 1c874d32217994a6faae1d2a24d07d19a3a52af2 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 19 Nov 2024 10:04:11 -0500 Subject: [PATCH 04/11] Fixed usage raisesException --- .../cpp/ir/implementation/raw/internal/TranslatedCall.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index a4c678869590..5f1b2fbe3b45 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -363,11 +363,11 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { } final override predicate mayThrowException() { - expr.getTarget().(ThrowingFunction).mayRaiseException() + expr.getTarget().(ThrowingFunction).raisesException(_) } final override predicate mustThrowException() { - expr.getTarget().(ThrowingFunction).alwaysRaisesException() + expr.getTarget().(ThrowingFunction).raisesException(true) } } From 26d590a616fba45b40fa3e5d47791b59c6d38d13 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 19 Nov 2024 12:57:50 -0500 Subject: [PATCH 05/11] Putting back deleted file, and deprecating instead. Deprecating mayThrowException as well. --- .../code/cpp/models/interfaces/NonThrowing.qll | 13 +++++++++++++ .../semmle/code/cpp/models/interfaces/Throwing.qll | 7 +++++++ 2 files changed, 20 insertions(+) create mode 100644 cpp/ql/lib/semmle/code/cpp/models/interfaces/NonThrowing.qll diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/NonThrowing.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/NonThrowing.qll new file mode 100644 index 000000000000..9f2c28979b44 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/NonThrowing.qll @@ -0,0 +1,13 @@ +/** + * Provides an abstract class for modeling functions that never throw. + */ + +import semmle.code.cpp.Function +import semmle.code.cpp.models.Models + +/** + * A function that is guaranteed to never throw. + * + * DEPRECATED: use `NonThrowingFunction` in `semmle.code.cpp.models.Models.Interfaces.Throwing` instead. + */ +abstract deprecated class NonThrowingFunction extends Function { } diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll index 72db8c9e96c7..bd64051d1415 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll @@ -68,6 +68,13 @@ abstract class ThrowingFunction extends ExceptionAnnotation { */ abstract predicate raisesException(boolean unconditional); + /** + * DEPRECATES: use/extend `raisesException` instead. + */ + deprecated predicate mayThrowException(boolean unconditional){ + this.raisesException(unconditional) + } + /** * Holds if this function will always raise an exception if called */ From 07847762e1f7dc87408c0e74dba32edcd5d0be56 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 19 Nov 2024 13:17:10 -0500 Subject: [PATCH 06/11] bringing back mayThrowException to make it cleaner/easier for backwards compatibility. --- .../raw/internal/TranslatedCall.qll | 4 ++-- .../code/cpp/models/interfaces/Throwing.qll | 17 ++--------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 5f1b2fbe3b45..daa6bdaafcf6 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -363,11 +363,11 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { } final override predicate mayThrowException() { - expr.getTarget().(ThrowingFunction).raisesException(_) + expr.getTarget().(ThrowingFunction).mayThrowException(_) } final override predicate mustThrowException() { - expr.getTarget().(ThrowingFunction).raisesException(true) + expr.getTarget().(ThrowingFunction).mayThrowException(true) } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll index bd64051d1415..db6bd689b4f1 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll @@ -66,23 +66,10 @@ abstract class ThrowingFunction extends ExceptionAnnotation { * Do not specify `none()` if no exception is raised, instead use the * `NonThrowingFunction` class instead. */ - abstract predicate raisesException(boolean unconditional); - - /** - * DEPRECATES: use/extend `raisesException` instead. - */ - deprecated predicate mayThrowException(boolean unconditional){ - this.raisesException(unconditional) - } + abstract predicate mayThrowException(boolean unconditional); /** * Holds if this function will always raise an exception if called */ - final predicate alwaysRaisesException() { this.raisesException(true) } - - /** - * Holds if this function may raise an exception if called but - * it is not guaranteed to do so. I.e., the function does not always raise an exception. - */ - final predicate mayRaiseException() { this.raisesException(false) } + final predicate alwaysRaisesException() { this.mayThrowException(true) } } From a69daa0d2018844fae600a420e7417de4f8600b8 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 19 Nov 2024 13:35:45 -0500 Subject: [PATCH 07/11] Missing change to 'mayThrowException' in StructuredExceptionHandling.qll --- .../cpp/models/implementations/StructuredExceptionHandling.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll index 485dc7137b81..36a2f6cdbe40 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/StructuredExceptionHandling.qll @@ -5,7 +5,7 @@ class WindowsDriverExceptionAnnotation extends ThrowingFunction { this.hasGlobalName(["RaiseException", "ExRaiseAccessViolation", "ExRaiseDatatypeMisalignment"]) } - override predicate raisesException(boolean unconditional) { unconditional = true } + override predicate mayThrowException(boolean unconditional) { unconditional = true } override TSehException getExceptionType() { any() } } From 4e777561f06ad9f891de48ab648135ebc50cd361 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Tue, 19 Nov 2024 15:10:15 -0500 Subject: [PATCH 08/11] Changing terminology back to "throws" vs "rasis" for alwaysThrowsException to be consistent with other backward compatibility changes. --- cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll index db6bd689b4f1..d64ba61caa0f 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll @@ -71,5 +71,5 @@ abstract class ThrowingFunction extends ExceptionAnnotation { /** * Holds if this function will always raise an exception if called */ - final predicate alwaysRaisesException() { this.mayThrowException(true) } + final predicate alwaysThrowsException() { this.mayThrowException(true) } } From 69df07ed1208ca12a82e83c1c2da9f430dbd458a Mon Sep 17 00:00:00 2001 From: Ben Rodes Date: Wed, 20 Nov 2024 09:06:44 -0500 Subject: [PATCH 09/11] Update cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md Co-authored-by: Mathias Vorreiter Pedersen --- cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md b/cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md index f3c33f40b517..114822e6c8f7 100644 --- a/cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md +++ b/cpp/ql/lib/change-notes/2024-11-18-throwing-functions.md @@ -1,4 +1,4 @@ --- -category: minorAnalysis +category: deprecated --- -* Removed NonThrowing.qll. Throwing meta-data now part of Throwing.qll. Updated models and IR to use the new Throwing library and predicates. \ No newline at end of file +* The `NonThrowing` class (`semmle.code.cpp.models.interfaces.NonThrowing`) has been deprecated. Please use the `NonThrowing` class from `semmle.code.cpp.models.interfaces.Throwing` instead. \ No newline at end of file From 4078d79f2a0a1ae9132ae19394970c0e6b743fef Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 20 Nov 2024 14:37:32 -0500 Subject: [PATCH 10/11] Adds SEH exception edge types, disjoint from normal C++ edges. Does not apply the edges yet, just stipulates the types. --- .../code/cpp/ir/implementation/EdgeKind.qll | 20 ++++++++++++++++--- .../raw/internal/TranslatedCall.qll | 2 +- .../raw/internal/TranslatedExpr.qll | 4 ++-- .../raw/internal/TranslatedStmt.qll | 2 +- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/EdgeKind.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/EdgeKind.qll index 81db183fa63e..38e20b651910 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/EdgeKind.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/EdgeKind.qll @@ -3,12 +3,13 @@ */ private import internal.EdgeKindInternal +private import codeql.util.Boolean private newtype TEdgeKind = TGotoEdge() or // Single successor (including fall-through) TTrueEdge() or // 'true' edge of conditional branch TFalseEdge() or // 'false' edge of conditional branch - TExceptionEdge() or // Thrown exception + TExceptionEdge(Boolean isSeh) or // Thrown exception, true for SEH exceptions, false otherwise TDefaultEdge() or // 'default' label of switch TCaseEdge(string minValue, string maxValue) { // Case label of switch @@ -54,7 +55,18 @@ class FalseEdge extends EdgeKind, TFalseEdge { * instruction's evaluation throws an exception. */ class ExceptionEdge extends EdgeKind, TExceptionEdge { - final override string toString() { result = "Exception" } + Boolean isSeh; //true for Structured Exception Handling, false for C++ exceptions + + ExceptionEdge() { this = TExceptionEdge(isSeh) } + + /** + * Holds if the exception is a Structured Exception Handling (SEH) exception. + */ + final predicate isSeh() { isSeh = true } + + final override string toString() { + if isSeh = true then result = "SEH Exception" else result = "C++ Exception" + } } /** @@ -122,8 +134,10 @@ module EdgeKind { /** * Gets the single instance of the `ExceptionEdge` class. + * Gets the instance of the `ExceptionEdge` class. + * `isSeh` is true if the exception is an SEH exception, and false for a C++ edge. */ - ExceptionEdge exceptionEdge() { result = TExceptionEdge() } + ExceptionEdge exceptionEdge(Boolean isSeh) { result = TExceptionEdge(isSeh) } /** * Gets the single instance of the `DefaultEdge` class. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index daa6bdaafcf6..16352ffaf7c4 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -88,7 +88,7 @@ abstract class TranslatedCall extends TranslatedExpr { result = this.getParent().getChildSuccessor(this, kind) or this.mayThrowException() and - kind instanceof ExceptionEdge and + kind = EdgeKind::exceptionEdge(false) and result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge)) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index e7ccac24eb92..5dc22a810f14 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -3039,7 +3039,7 @@ class TranslatedDestructorsAfterThrow extends TranslatedElement, TTranslatedDest or // And otherwise, exit this element with an exceptional edge not exists(this.getChild(id + 1)) and - kind instanceof ExceptionEdge and + kind = EdgeKind::exceptionEdge(false) and result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge)) ) } @@ -3078,7 +3078,7 @@ abstract class TranslatedThrowExpr extends TranslatedNonConstantExpr { result = this.getDestructors().getFirstInstruction(kind) or not exists(this.getDestructors()) and - kind instanceof ExceptionEdge and + kind = EdgeKind::exceptionEdge(false) and result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge)) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index e37df72abbd0..5f70a21fdb82 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -932,7 +932,7 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler { kind instanceof GotoEdge and result = this.getParameter().getFirstInstruction(kind) or - kind instanceof ExceptionEdge and + kind = EdgeKind::exceptionEdge(false) and if exists(this.getDestructors()) then result = this.getDestructors().getFirstInstruction(any(GotoEdge edge)) else result = this.getParent().(TranslatedTryStmt).getNextHandler(this, any(GotoEdge edge)) From 007dd837994ae0105c9cd8d4d5f2abfaeef0944c Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 20 Nov 2024 14:40:58 -0500 Subject: [PATCH 11/11] Updating ir test expected files. --- .../library-tests/ir/ir/aliased_ir.expected | 58 +++++++-------- .../test/library-tests/ir/ir/raw_ir.expected | 74 +++++++++---------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index 28fde3672d9b..224ac9a0ed9b 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -2490,7 +2490,7 @@ destructors_for_temps.cpp: # 47| v47_6(void) = ^IndirectReadSideEffect[-1] : &:r47_1, ~m47_5 # 47| m47_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r47_1 # 47| m47_8(unknown) = Chi : total:m47_5, partial:m47_7 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 47| Block 4 # 47| v47_9(void) = NoOp : @@ -2574,7 +2574,7 @@ destructors_for_temps.cpp: # 52| v52_6(void) = ^IndirectReadSideEffect[-1] : &:r52_1, ~m52_5 # 52| m52_7(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r52_1 # 52| m52_8(unknown) = Chi : total:m52_5, partial:m52_7 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 51| Block 4 # 51| r51_32(glval) = VariableAddress[#temp51:75] : @@ -2656,7 +2656,7 @@ destructors_for_temps.cpp: # 55| m55_29(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r55_5 # 55| m55_30(unknown) = Chi : total:m55_28, partial:m55_29 # 55| v55_31(void) = ThrowValue : &:r55_5, ~m55_30 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 55| Block 4 # 55| r55_32(glval) = VariableAddress[#temp55:75] : @@ -2721,7 +2721,7 @@ destructors_for_temps.cpp: # 59| m59_20(unknown) = Chi : total:m59_17, partial:m59_19 # 59| m59_21(char) = Store[#throw59:9] : &:r59_4, r59_15 # 59| v59_22(void) = ThrowValue : &:r59_4, m59_21 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 59| Block 4 # 59| r59_23(char) = Constant[97] : @@ -3120,7 +3120,7 @@ ir.c: # 25| v25_4(void) = Call[ExRaiseAccessViolation] : func:r25_1, 0:r25_3 # 25| m25_5(unknown) = ^CallSideEffect : ~m21_4 # 25| m25_6(unknown) = Chi : total:m21_4, partial:m25_5 -#-----| Exception -> Block 3 +#-----| C++ Exception -> Block 3 # 26| Block 1 # 26| r26_1(int) = Constant[0] : @@ -3167,7 +3167,7 @@ ir.c: # 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2 # 36| m36_4(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_5(unknown) = Chi : total:m32_4, partial:m36_4 -#-----| Exception -> Block 4 +#-----| C++ Exception -> Block 4 # 32| Block 1 # 32| v32_5(void) = Unwind : @@ -3202,7 +3202,7 @@ ir.c: # 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2 # 40| m40_4(unknown) = ^CallSideEffect : ~m36_5 # 40| m40_5(unknown) = Chi : total:m36_5, partial:m40_4 -#-----| Exception -> Block 1 +#-----| C++ Exception -> Block 1 # 32| Block 6 # 32| v32_8(void) = Unreached : @@ -3241,7 +3241,7 @@ ir.c: # 62| v62_3(void) = Call[ExRaiseAccessViolation] : func:r62_1, 0:r62_2 # 62| m62_4(unknown) = ^CallSideEffect : ~m57_4 # 62| m62_5(unknown) = Chi : total:m57_4, partial:m62_4 -#-----| Exception -> Block 1 +#-----| C++ Exception -> Block 1 # 66| Block 1 # 66| r66_1(int) = Constant[1] : @@ -3263,7 +3263,7 @@ ir.c: # 73| v73_3(void) = Call[ExRaiseAccessViolation] : func:r73_1, 0:r73_2 # 73| m73_4(unknown) = ^CallSideEffect : ~m70_4 # 73| m73_5(unknown) = Chi : total:m70_4, partial:m73_4 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 70| Block 1 # 70| v70_5(void) = Unwind : @@ -3276,7 +3276,7 @@ ir.c: # 76| v76_3(void) = Call[ExRaiseAccessViolation] : func:r76_1, 0:r76_2 # 76| m76_4(unknown) = ^CallSideEffect : ~m73_5 # 76| m76_5(unknown) = Chi : total:m73_5, partial:m76_4 -#-----| Exception -> Block 1 +#-----| C++ Exception -> Block 1 # 80| void raise_access_violation() # 80| Block 0 @@ -3289,7 +3289,7 @@ ir.c: # 81| v81_3(void) = Call[ExRaiseAccessViolation] : func:r81_1, 0:r81_2 # 81| m81_4(unknown) = ^CallSideEffect : ~m80_4 # 81| m81_5(unknown) = Chi : total:m80_4, partial:m81_4 -#-----| Exception -> Block 1 +#-----| C++ Exception -> Block 1 # 80| Block 1 # 80| v80_5(void) = Unwind : @@ -6976,7 +6976,7 @@ ir.cpp: # 728| r728_3(char *) = Convert : r728_2 # 728| m728_4(char *) = Store[#throw728:7] : &:r728_1, r728_3 # 728| v728_5(void) = ThrowValue : &:r728_1, m728_4 -#-----| Exception -> Block 6 +#-----| C++ Exception -> Block 6 # 730| Block 4 # 730| r730_1(glval) = VariableAddress[x] : @@ -6995,7 +6995,7 @@ ir.cpp: # 735| Block 6 # 735| v735_1(void) = CatchByType[const char *] : -#-----| Exception -> Block 8 +#-----| C++ Exception -> Block 8 #-----| Goto -> Block 7 # 735| Block 7 @@ -7017,11 +7017,11 @@ ir.cpp: # 736| m736_11(String) = ^IndirectMayWriteSideEffect[-1] : &:r736_1 # 736| m736_12(unknown) = Chi : total:m736_9, partial:m736_11 # 736| v736_13(void) = ThrowValue : &:r736_1, ~m736_12 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 738| Block 8 # 738| v738_1(void) = CatchByType[const String &] : -#-----| Exception -> Block 10 +#-----| C++ Exception -> Block 10 #-----| Goto -> Block 9 # 738| Block 9 @@ -7035,7 +7035,7 @@ ir.cpp: # 740| Block 10 # 740| v740_1(void) = CatchAny : # 741| v741_1(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 743| Block 11 # 743| v743_1(void) = NoOp : @@ -9943,7 +9943,7 @@ ir.cpp: # 1195| r1195_3(char *) = Convert : r1195_2 # 1195| m1195_4(char *) = Store[#throw1195:7] : &:r1195_1, r1195_3 # 1195| v1195_5(void) = ThrowValue : &:r1195_1, m1195_4 -#-----| Exception -> Block 6 +#-----| C++ Exception -> Block 6 # 1197| Block 4 # 1197| r1197_1(glval) = VariableAddress[x] : @@ -9962,7 +9962,7 @@ ir.cpp: # 1202| Block 6 # 1202| v1202_1(void) = CatchByType[const char *] : -#-----| Exception -> Block 8 +#-----| C++ Exception -> Block 8 #-----| Goto -> Block 7 # 1202| Block 7 @@ -9984,11 +9984,11 @@ ir.cpp: # 1203| m1203_11(String) = ^IndirectMayWriteSideEffect[-1] : &:r1203_1 # 1203| m1203_12(unknown) = Chi : total:m1203_9, partial:m1203_11 # 1203| v1203_13(void) = ThrowValue : &:r1203_1, ~m1203_12 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 1205| Block 8 # 1205| v1205_1(void) = CatchByType[const String &] : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 #-----| Goto -> Block 9 # 1205| Block 9 @@ -16924,7 +16924,7 @@ ir.cpp: # 2281| v2281_6(void) = ^IndirectReadSideEffect[-1] : &:r2281_1, ~m2281_5 # 2281| m2281_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r2281_1 # 2281| m2281_8(unknown) = Chi : total:m2281_5, partial:m2281_7 -#-----| Exception -> Block 5 +#-----| C++ Exception -> Block 5 # 2280| Block 4 # 2280| r2280_1(glval) = VariableAddress[s2] : @@ -16956,7 +16956,7 @@ ir.cpp: # 2282| Block 5 # 2282| v2282_1(void) = CatchByType[const char *] : -#-----| Exception -> Block 7 +#-----| C++ Exception -> Block 7 #-----| Goto -> Block 6 # 2282| Block 6 @@ -16978,11 +16978,11 @@ ir.cpp: # 2283| m2283_11(String) = ^IndirectMayWriteSideEffect[-1] : &:r2283_1 # 2283| m2283_12(unknown) = Chi : total:m2283_9, partial:m2283_11 # 2283| v2283_13(void) = ThrowValue : &:r2283_1, ~m2283_12 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 2285| Block 7 # 2285| v2285_1(void) = CatchByType[const String &] : -#-----| Exception -> Block 9 +#-----| C++ Exception -> Block 9 #-----| Goto -> Block 8 # 2285| Block 8 @@ -16996,7 +16996,7 @@ ir.cpp: # 2287| Block 9 # 2287| v2287_1(void) = CatchAny : # 2288| v2288_1(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 2290| Block 10 # 2290| m2290_1(unknown) = Phi : from 4:~m2281_24, from 8:~m2281_8 @@ -18266,7 +18266,7 @@ ir.cpp: # 2454| v2454_6(void) = ^IndirectReadSideEffect[-1] : &:r2454_1, m2452_8 # 2454| m2454_7(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2454_1 # 2454| m2454_8(ClassWithDestructor) = Chi : total:m2452_8, partial:m2454_7 -#-----| Exception -> Block 1 +#-----| C++ Exception -> Block 1 # 2451| Block 1 # 2451| v2451_7(void) = Unwind : @@ -18693,7 +18693,7 @@ ir.cpp: # 2537| r2537_2(int) = Constant[42] : # 2537| m2537_3(int) = Store[#throw2537:5] : &:r2537_1, r2537_2 # 2537| v2537_4(void) = ThrowValue : &:r2537_1, m2537_3 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 2534| Block 1 # 2534| m2534_5(unknown) = Phi : from 3:~m2541_6, from 4:~m2541_14 @@ -18702,7 +18702,7 @@ ir.cpp: # 2539| Block 2 # 2539| v2539_1(void) = CatchByType[char] : -#-----| Exception -> Block 4 +#-----| C++ Exception -> Block 4 #-----| Goto -> Block 3 # 2539| Block 3 @@ -38962,7 +38962,7 @@ try_except.cpp: # 48| r48_2(int) = Constant[1] : # 48| m48_3(int) = Store[#throw48:13] : &:r48_1, r48_2 # 48| v48_4(void) = ThrowValue : &:r48_1, m48_3 -#-----| Exception -> Block 4 +#-----| C++ Exception -> Block 4 # 51| Block 2 # 51| r51_1(int) = Constant[0] : diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 0093a108577a..8600049dd225 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -822,7 +822,7 @@ coroutines.cpp: #-----| Block 6 #-----| v0_24(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 87| Block 7 # 87| r87_52(glval) = VariableAddress[(unnamed local variable)] : @@ -1001,7 +1001,7 @@ coroutines.cpp: #-----| Block 6 #-----| v0_28(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 91| Block 7 # 91| r91_54(glval) = VariableAddress[(unnamed local variable)] : @@ -1239,7 +1239,7 @@ coroutines.cpp: #-----| Block 8 #-----| v0_34(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 95| Block 9 # 95| r95_54(glval) = VariableAddress[(unnamed local variable)] : @@ -1469,7 +1469,7 @@ coroutines.cpp: #-----| Block 8 #-----| v0_27(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 99| Block 9 # 99| r99_54(glval) = VariableAddress[(unnamed local variable)] : @@ -1707,7 +1707,7 @@ coroutines.cpp: #-----| Block 8 #-----| v0_34(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 103| Block 9 # 103| r103_54(glval) = VariableAddress[(unnamed local variable)] : @@ -1949,7 +1949,7 @@ coroutines.cpp: #-----| Block 8 #-----| v0_34(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 108| Block 9 # 108| r108_54(glval) = VariableAddress[(unnamed local variable)] : @@ -2350,7 +2350,7 @@ destructors_for_temps.cpp: # 47| mu47_4(unknown) = ^CallSideEffect : ~m? # 47| v47_5(void) = ^IndirectReadSideEffect[-1] : &:r47_1, ~m? # 47| mu47_6(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r47_1 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 47| Block 4 # 47| v47_7(void) = NoOp : @@ -2417,7 +2417,7 @@ destructors_for_temps.cpp: # 52| mu52_4(unknown) = ^CallSideEffect : ~m? # 52| v52_5(void) = ^IndirectReadSideEffect[-1] : &:r52_1, ~m? # 52| mu52_6(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r52_1 -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 51| Block 4 # 51| r51_24(glval) = VariableAddress[#temp51:75] : @@ -2484,7 +2484,7 @@ destructors_for_temps.cpp: # 55| mu55_21(unknown) = ^CallSideEffect : ~m? # 55| mu55_22(ClassWithConstructor) = ^IndirectMayWriteSideEffect[-1] : &:r55_5 # 55| v55_23(void) = ThrowValue : &:r55_5, ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 55| Block 4 # 55| r55_24(glval) = VariableAddress[#temp55:75] : @@ -2539,7 +2539,7 @@ destructors_for_temps.cpp: # 59| mu59_15(ClassWithDestructor2) = ^IndirectMayWriteSideEffect[-1] : &:r59_5 # 59| mu59_16(char) = Store[#throw59:9] : &:r59_4, r59_12 # 59| v59_17(void) = ThrowValue : &:r59_4, ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 59| Block 4 # 59| r59_18(char) = Constant[97] : @@ -2884,7 +2884,7 @@ ir.c: # 25| r25_3(int) = Load[x] : &:r25_2, ~m? # 25| v25_4(void) = Call[ExRaiseAccessViolation] : func:r25_1, 0:r25_3 # 25| mu25_5(unknown) = ^CallSideEffect : ~m? -#-----| Exception -> Block 6 +#-----| C++ Exception -> Block 6 # 21| Block 1 # 21| v21_6(void) = AliasedUse : ~m? @@ -2941,7 +2941,7 @@ ir.c: # 36| r36_2(int) = Constant[0] : # 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2 # 36| mu36_4(unknown) = ^CallSideEffect : ~m? -#-----| Exception -> Block 5 +#-----| C++ Exception -> Block 5 # 32| Block 1 # 32| v32_4(void) = AliasedUse : ~m? @@ -2977,7 +2977,7 @@ ir.c: # 40| r40_2(int) = Constant[1] : # 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2 # 40| mu40_4(unknown) = ^CallSideEffect : ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 42| Block 7 # 42| v42_1(void) = NoOp : @@ -3022,7 +3022,7 @@ ir.c: # 62| r62_2(int) = Constant[0] : # 62| v62_3(void) = Call[ExRaiseAccessViolation] : func:r62_1, 0:r62_2 # 62| mu62_4(unknown) = ^CallSideEffect : ~m? -#-----| Exception -> Block 3 +#-----| C++ Exception -> Block 3 # 57| Block 1 # 57| v57_4(void) = AliasedUse : ~m? @@ -3049,7 +3049,7 @@ ir.c: # 73| r73_2(int) = Constant[0] : # 73| v73_3(void) = Call[ExRaiseAccessViolation] : func:r73_1, 0:r73_2 # 73| mu73_4(unknown) = ^CallSideEffect : ~m? -#-----| Exception -> Block 3 +#-----| C++ Exception -> Block 3 # 70| Block 1 # 70| v70_4(void) = AliasedUse : ~m? @@ -3064,7 +3064,7 @@ ir.c: # 76| r76_2(int) = Constant[0] : # 76| v76_3(void) = Call[ExRaiseAccessViolation] : func:r76_1, 0:r76_2 # 76| mu76_4(unknown) = ^CallSideEffect : ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 78| Block 4 # 78| v78_1(void) = NoOp : @@ -3080,7 +3080,7 @@ ir.c: # 81| r81_2(int) = Constant[1] : # 81| v81_3(void) = Call[ExRaiseAccessViolation] : func:r81_1, 0:r81_2 # 81| mu81_4(unknown) = ^CallSideEffect : ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 80| Block 1 # 80| v80_4(void) = AliasedUse : ~m? @@ -6615,7 +6615,7 @@ ir.cpp: # 728| r728_3(char *) = Convert : r728_2 # 728| mu728_4(char *) = Store[#throw728:7] : &:r728_1, r728_3 # 728| v728_5(void) = ThrowValue : &:r728_1, ~m? -#-----| Exception -> Block 9 +#-----| C++ Exception -> Block 9 # 730| Block 4 # 730| r730_1(glval) = VariableAddress[x] : @@ -6654,7 +6654,7 @@ ir.cpp: # 731| v731_18(void) = ^BufferReadSideEffect[0] : &:r731_15, ~m? # 731| mu731_19(String) = ^IndirectMayWriteSideEffect[-1] : &:r731_11 # 731| v731_20(void) = ThrowValue : &:r731_11, ~m? -#-----| Exception -> Block 9 +#-----| C++ Exception -> Block 9 # 733| Block 8 # 733| r733_1(int) = Constant[7] : @@ -6664,7 +6664,7 @@ ir.cpp: # 735| Block 9 # 735| v735_1(void) = CatchByType[const char *] : -#-----| Exception -> Block 11 +#-----| C++ Exception -> Block 11 #-----| Goto -> Block 10 # 735| Block 10 @@ -6682,11 +6682,11 @@ ir.cpp: # 736| v736_8(void) = ^BufferReadSideEffect[0] : &:r736_5, ~m? # 736| mu736_9(String) = ^IndirectMayWriteSideEffect[-1] : &:r736_1 # 736| v736_10(void) = ThrowValue : &:r736_1, ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 738| Block 11 # 738| v738_1(void) = CatchByType[const String &] : -#-----| Exception -> Block 13 +#-----| C++ Exception -> Block 13 #-----| Goto -> Block 12 # 738| Block 12 @@ -6700,7 +6700,7 @@ ir.cpp: # 740| Block 13 # 740| v740_1(void) = CatchAny : # 741| v741_1(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 743| Block 14 # 743| v743_1(void) = NoOp : @@ -9285,7 +9285,7 @@ ir.cpp: # 1195| r1195_3(char *) = Convert : r1195_2 # 1195| mu1195_4(char *) = Store[#throw1195:7] : &:r1195_1, r1195_3 # 1195| v1195_5(void) = ThrowValue : &:r1195_1, ~m? -#-----| Exception -> Block 9 +#-----| C++ Exception -> Block 9 # 1197| Block 4 # 1197| r1197_1(glval) = VariableAddress[x] : @@ -9324,7 +9324,7 @@ ir.cpp: # 1198| v1198_18(void) = ^BufferReadSideEffect[0] : &:r1198_15, ~m? # 1198| mu1198_19(String) = ^IndirectMayWriteSideEffect[-1] : &:r1198_11 # 1198| v1198_20(void) = ThrowValue : &:r1198_11, ~m? -#-----| Exception -> Block 9 +#-----| C++ Exception -> Block 9 # 1200| Block 8 # 1200| r1200_1(int) = Constant[7] : @@ -9334,7 +9334,7 @@ ir.cpp: # 1202| Block 9 # 1202| v1202_1(void) = CatchByType[const char *] : -#-----| Exception -> Block 11 +#-----| C++ Exception -> Block 11 #-----| Goto -> Block 10 # 1202| Block 10 @@ -9352,11 +9352,11 @@ ir.cpp: # 1203| v1203_8(void) = ^BufferReadSideEffect[0] : &:r1203_5, ~m? # 1203| mu1203_9(String) = ^IndirectMayWriteSideEffect[-1] : &:r1203_1 # 1203| v1203_10(void) = ThrowValue : &:r1203_1, ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 1205| Block 11 # 1205| v1205_1(void) = CatchByType[const String &] : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 #-----| Goto -> Block 12 # 1205| Block 12 @@ -15571,7 +15571,7 @@ ir.cpp: # 2281| mu2281_4(unknown) = ^CallSideEffect : ~m? # 2281| v2281_5(void) = ^IndirectReadSideEffect[-1] : &:r2281_1, ~m? # 2281| mu2281_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r2281_1 -#-----| Exception -> Block 5 +#-----| C++ Exception -> Block 5 # 2280| Block 4 # 2280| r2280_1(glval) = VariableAddress[s2] : @@ -15596,7 +15596,7 @@ ir.cpp: # 2282| Block 5 # 2282| v2282_1(void) = CatchByType[const char *] : -#-----| Exception -> Block 7 +#-----| C++ Exception -> Block 7 #-----| Goto -> Block 6 # 2282| Block 6 @@ -15614,11 +15614,11 @@ ir.cpp: # 2283| v2283_8(void) = ^BufferReadSideEffect[0] : &:r2283_5, ~m? # 2283| mu2283_9(String) = ^IndirectMayWriteSideEffect[-1] : &:r2283_1 # 2283| v2283_10(void) = ThrowValue : &:r2283_1, ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 2285| Block 7 # 2285| v2285_1(void) = CatchByType[const String &] : -#-----| Exception -> Block 9 +#-----| C++ Exception -> Block 9 #-----| Goto -> Block 8 # 2285| Block 8 @@ -15632,7 +15632,7 @@ ir.cpp: # 2287| Block 9 # 2287| v2287_1(void) = CatchAny : # 2288| v2288_1(void) = ReThrow : -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 2290| Block 10 # 2290| v2290_1(void) = NoOp : @@ -16699,7 +16699,7 @@ ir.cpp: # 2454| mu2454_4(unknown) = ^CallSideEffect : ~m? # 2454| v2454_5(void) = ^IndirectReadSideEffect[-1] : &:r2454_1, ~m? # 2454| mu2454_6(ClassWithDestructor) = ^IndirectMayWriteSideEffect[-1] : &:r2454_1 -#-----| Exception -> Block 3 +#-----| C++ Exception -> Block 3 # 2451| Block 1 # 2451| v2451_6(void) = AliasedUse : ~m? @@ -17102,7 +17102,7 @@ ir.cpp: # 2537| r2537_2(int) = Constant[42] : # 2537| mu2537_3(int) = Store[#throw2537:5] : &:r2537_1, r2537_2 # 2537| v2537_4(void) = ThrowValue : &:r2537_1, ~m? -#-----| Exception -> Block 2 +#-----| C++ Exception -> Block 2 # 2534| Block 1 # 2534| v2534_4(void) = AliasedUse : ~m? @@ -17110,7 +17110,7 @@ ir.cpp: # 2539| Block 2 # 2539| v2539_1(void) = CatchByType[char] : -#-----| Exception -> Block 4 +#-----| C++ Exception -> Block 4 #-----| Goto -> Block 3 # 2539| Block 3 @@ -37343,7 +37343,7 @@ try_except.cpp: # 48| r48_2(int) = Constant[1] : # 48| mu48_3(int) = Store[#throw48:13] : &:r48_1, r48_2 # 48| v48_4(void) = ThrowValue : &:r48_1, ~m? -#-----| Exception -> Block 6 +#-----| C++ Exception -> Block 6 # 51| Block 4 # 51| r51_1(int) = Constant[0] :