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/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