diff --git a/cpp/ql/lib/DefaultOptions.qll b/cpp/ql/lib/DefaultOptions.qll index ae3ca205188..73a891bb554 100644 --- a/cpp/ql/lib/DefaultOptions.qll +++ b/cpp/ql/lib/DefaultOptions.qll @@ -54,11 +54,13 @@ class Options extends string { * * By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`, * `longjmp`, `__builtin_unreachable` and any function with a - * `noreturn` attribute. + * `noreturn` attribute or specifier. */ predicate exits(Function f) { f.getAnAttribute().hasName("noreturn") or + f.getASpecifier().hasName("noreturn") + or f.hasGlobalOrStdName([ "exit", "_exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable" ]) diff --git a/cpp/ql/lib/Options.qll b/cpp/ql/lib/Options.qll index b18aede94f2..a0a13881a94 100644 --- a/cpp/ql/lib/Options.qll +++ b/cpp/ql/lib/Options.qll @@ -39,7 +39,7 @@ class CustomOptions extends Options { * * By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`, * `longjmp`, `error`, `__builtin_unreachable` and any function with a - * `noreturn` attribute. + * `noreturn` attribute or specifier. */ override predicate exits(Function f) { Options.super.exits(f) } diff --git a/cpp/ql/lib/change-notes/2022-03-14-c11-noreturn.md b/cpp/ql/lib/change-notes/2022-03-14-c11-noreturn.md new file mode 100644 index 00000000000..c74e1ab9820 --- /dev/null +++ b/cpp/ql/lib/change-notes/2022-03-14-c11-noreturn.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* `DefaultOptions::exits` now holds for C11 functions with the `_Noreturn` or `noreturn` specifier. diff --git a/cpp/ql/lib/semmle/code/cpp/Specifier.qll b/cpp/ql/lib/semmle/code/cpp/Specifier.qll index 69cccf06ffb..7a13b13e8c2 100644 --- a/cpp/ql/lib/semmle/code/cpp/Specifier.qll +++ b/cpp/ql/lib/semmle/code/cpp/Specifier.qll @@ -38,7 +38,7 @@ class FunctionSpecifier extends Specifier { /** * A C/C++ storage class specifier: `auto`, `register`, `static`, `extern`, - * or `mutable". + * or `mutable`. */ class StorageClassSpecifier extends Specifier { StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) } diff --git a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.c b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.c index 82c860c6e9b..fcda0b8087a 100644 --- a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.c +++ b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.c @@ -1,4 +1,4 @@ - +// semmle-extractor-options: -std=c11 int f1(void) { int x = 1; return 2; @@ -99,3 +99,9 @@ int f14() { __asm__("rdtsc"); // GOOD } + +_Noreturn void f15(); + +int f16() { + f15(); // GOOD +} diff --git a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp index 875c9ec4f75..c68ad23805c 100644 --- a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp +++ b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp @@ -1,4 +1,4 @@ - +// semmle-extractor-options: -std=c++11 class MyValue { public: MyValue(int _val) : val(_val) {}; @@ -164,3 +164,9 @@ int g19(int x) return x; // GOOD } + +[[noreturn]] void g20(); + +int g21() { + g20(); // GOOD +}