From e7dfb3e61b6be8012a62ffe456dd56656db84cd1 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 28 Aug 2019 11:34:16 +0200 Subject: [PATCH 1/2] C++: Test for x-macro FP observed in the wild --- .../jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected | 1 + .../query-tests/jsf/4.07 Header Files/AV Rule 35/all1.cpp | 5 +++++ .../query-tests/jsf/4.07 Header Files/AV Rule 35/all2.cpp | 4 ++++ .../query-tests/jsf/4.07 Header Files/AV Rule 35/items3.h | 5 +++++ 4 files changed, 15 insertions(+) create mode 100644 cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/items3.h diff --git a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected index ae8a723870a..fa2cab0b6cc 100644 --- a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected +++ b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected @@ -1,6 +1,7 @@ | complexcondition2.h:0:0:0:0 | complexcondition2.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | | complexcondition.h:0:0:0:0 | complexcondition.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | | fundecl.h:0:0:0:0 | fundecl.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | +| items3.h:0:0:0:0 | items3.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | | multipleguards.h:0:0:0:0 | multipleguards.h | This header file should contain a header guard to prevent multiple inclusion ($@ matching $@ occurs before the end of the file). | multipleguards.h:7:1:7:6 | #endif | #endif | multipleguards.h:2:1:2:24 | #ifndef MULTIPLEGUARDS_H | #ifndef MULTIPLEGUARDS_H | | namespace1.h:0:0:0:0 | namespace1.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | | namespace2.h:0:0:0:0 | namespace2.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | diff --git a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/all1.cpp b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/all1.cpp index d6d07ad004b..e04d23ab550 100644 --- a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/all1.cpp +++ b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/all1.cpp @@ -53,3 +53,8 @@ enum Items { #define XMACRO2(id,desc) void use_##(); #include "items2.h" #undef XMACRO2 + + +#define XMACRO3(id,desc) static const char * id##_item = "The " desc " item"; + #include "items3.h" +// No #undef of XMACRO3. That's handled in items3.h. diff --git a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/all2.cpp b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/all2.cpp index f55b669191d..09ed19c0ea6 100644 --- a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/all2.cpp +++ b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/all2.cpp @@ -32,3 +32,7 @@ enum Items { #define XMACRO2(id,desc) void use_##(); #include "items2.h" #undef XMACRO2 + +#define XMACRO3(id,desc) static const char * id##_name = desc; + #include "items3.h" +// No #undef of XMACRO3. That's handled in items3.h. diff --git a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/items3.h b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/items3.h new file mode 100644 index 00000000000..70f05aba8a9 --- /dev/null +++ b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/items3.h @@ -0,0 +1,5 @@ +XMACRO3(shield, "Wooden Shield") +XMACRO3(boots, "Leather Boots") +XMACRO3(helmet, "Helmet") + +#undef XMACRO3 From 2c253f360a4c5d3bbd9c665fe4b8e6bed01751d1 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 28 Aug 2019 11:56:50 +0200 Subject: [PATCH 2/2] C++: Support x-macros that are #undef'ed in header This fixes a false positive on https://github.com/zduka/tpp. --- .../src/jsf/4.07 Header Files/AV Rule 35.ql | 37 +++++++++++++++---- .../AV Rule 35/AV Rule 35.expected | 1 - 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql index d59a7690e7b..92f6b77822e 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql @@ -95,17 +95,28 @@ predicate usesMacro(HeaderFile hf, string macroName) { ) } +/** File `f` defines a macro called `macroName`. */ +predicate definesMacro(File f, string macroName) { + exists(Macro m | + m.getFile() = f and + m.getName() = macroName + ) +} + +/** File `f` un-defines a macro called `macroName`. */ +predicate undefinesMacro(File f, string macroName) { + exists(PreprocessorUndef ud | + ud.getFile() = f and + ud.getName() = macroName + ) +} + /** * File `f` both defines and un-defines a macro called `macroName`. */ predicate defUndef(File f, string macroName) { - exists(Macro m | - m.getFile() = f and - m.getName() = macroName - ) and exists(PreprocessorUndef ud | - ud.getFile() = f and - ud.getName() = macroName - ) + definesMacro(f, macroName) and + undefinesMacro(f, macroName) } /** @@ -115,12 +126,24 @@ predicate defUndef(File f, string macroName) { * and undefined immediately afterwards. */ predicate hasXMacro(HeaderFile hf) { + // Every header that includes `hf` both defines and undefines a macro that's + // used in `hf`. exists(string macroName | usesMacro(hf, macroName) and forex(File f | f.getAnIncludedFile() = hf | defUndef(f, macroName) ) ) + or + // Every header that includes `hf` defines a macro that's used in `hf`, and + // `hf` itself undefines it. + exists(string macroName | + usesMacro(hf, macroName) and + undefinesMacro(hf, macroName) and + forex(File f | f.getAnIncludedFile() = hf | + definesMacro(f, macroName) + ) + ) } from HeaderFile hf, string detail, MaybePreprocessorDirective detail1, MaybePreprocessorDirective detail2 diff --git a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected index fa2cab0b6cc..ae8a723870a 100644 --- a/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected +++ b/cpp/ql/test/query-tests/jsf/4.07 Header Files/AV Rule 35/AV Rule 35.expected @@ -1,7 +1,6 @@ | complexcondition2.h:0:0:0:0 | complexcondition2.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | | complexcondition.h:0:0:0:0 | complexcondition.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | | fundecl.h:0:0:0:0 | fundecl.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | -| items3.h:0:0:0:0 | items3.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | | multipleguards.h:0:0:0:0 | multipleguards.h | This header file should contain a header guard to prevent multiple inclusion ($@ matching $@ occurs before the end of the file). | multipleguards.h:7:1:7:6 | #endif | #endif | multipleguards.h:2:1:2:24 | #ifndef MULTIPLEGUARDS_H | #ifndef MULTIPLEGUARDS_H | | namespace1.h:0:0:0:0 | namespace1.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | | | namespace2.h:0:0:0:0 | namespace2.h | This header file should contain a header guard to prevent multiple inclusion. | file://:0:0:0:0 | | | file://:0:0:0:0 | | |