diff --git a/cpp/autosar/src/codingstandards/cpp/CommonTypes.qll b/cpp/autosar/src/codingstandards/cpp/CommonTypes.qll index aafbe85433..3c8ea46b08 100644 --- a/cpp/autosar/src/codingstandards/cpp/CommonTypes.qll +++ b/cpp/autosar/src/codingstandards/cpp/CommonTypes.qll @@ -1,7 +1,7 @@ import cpp as default /* - * Implementations of the C/C++ Fixed Width Types from cstdint.h. + * Implementations of the C/C++ Fixed Width Types from cstdint. * * TODO: Deprecate once this is available in the CodeQL standard library. */ diff --git a/cpp/common/src/codingstandards/cpp/BannedFunctions.qll b/cpp/common/src/codingstandards/cpp/BannedFunctions.qll new file mode 100644 index 0000000000..174d0a8433 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/BannedFunctions.qll @@ -0,0 +1,69 @@ +/** + * A library for supporting the consistent detection of banned functions in C++ code. + */ + +import cpp +import AlertReporting + +/** + * A signature for a banned function. + */ +signature class BannedFunction extends Function; + +/** + * A module for detecting uses of banned functions in C++ code. + */ +module BannedFunctions { + final private class FinalExpr = Expr; + + /** + * An expression that uses a banned function. + * + * It can be either a function call or a function access (taking the address of the function). + */ + class UseExpr extends FinalExpr { + string action; + F bannedFunction; + + UseExpr() { + this.(FunctionCall).getTarget() = bannedFunction and + action = "Call to" + or + this.(FunctionAccess).getTarget() = bannedFunction and + action = "Address taken for" + } + + string getFunctionName() { result = bannedFunction.getName() } + + string getAction() { result = action } + + Element getPrimaryElement() { + // If this is defined in a macro in the users source location, then report the macro + // expansion, otherwise report the element itself. This ensures that we always report + // the use of the terminating function, but combine usages when the macro is defined + // by the user. + exists(Element e | e = MacroUnwrapper::unwrapElement(this) | + if exists(e.getFile().getRelativePath()) then result = e else result = this + ) + } + } + + final private class FinalElement = Element; + + /** + * A `Use` of a banned function. + * + * This is an `Element` in a program which represents the use of a banned function. + * For uses within macro expansions, this may report the location of the macro, if + * it is defined within the user's source code. + */ + class Use extends FinalElement { + UseExpr use; + + Use() { this = use.getPrimaryElement() } + + string getFunctionName() { result = use.getFunctionName() } + + string getAction() { result = use.getAction() } + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedAPIs.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedAPIs.qll new file mode 100644 index 0000000000..571a48a625 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedAPIs.qll @@ -0,0 +1,163 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype BannedAPIsQuery = + TAvoidProgramTerminatingFunctionsQuery() or + TNoVariadicFunctionMacrosQuery() or + TNoCsetjmpHeaderQuery() or + TUnsafeStringHandlingFunctionsQuery() or + TBannedSystemFunctionQuery() or + TUseSmartPtrFactoryFunctionsQuery() or + TCharacterHandlingFunctionRestrictionsQuery() or + TNoMemoryFunctionsFromCStringQuery() or + TLocaleGlobalFunctionNotAllowedQuery() + +predicate isBannedAPIsQueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `avoidProgramTerminatingFunctions` query + BannedAPIsPackage::avoidProgramTerminatingFunctionsQuery() and + queryId = + // `@id` for the `avoidProgramTerminatingFunctions` query + "cpp/misra/avoid-program-terminating-functions" and + ruleId = "RULE-18-5-2" and + category = "advisory" + or + query = + // `Query` instance for the `noVariadicFunctionMacros` query + BannedAPIsPackage::noVariadicFunctionMacrosQuery() and + queryId = + // `@id` for the `noVariadicFunctionMacros` query + "cpp/misra/no-variadic-function-macros" and + ruleId = "RULE-21-10-1" and + category = "required" + or + query = + // `Query` instance for the `noCsetjmpHeader` query + BannedAPIsPackage::noCsetjmpHeaderQuery() and + queryId = + // `@id` for the `noCsetjmpHeader` query + "cpp/misra/no-csetjmp-header" and + ruleId = "RULE-21-10-2" and + category = "required" + or + query = + // `Query` instance for the `unsafeStringHandlingFunctions` query + BannedAPIsPackage::unsafeStringHandlingFunctionsQuery() and + queryId = + // `@id` for the `unsafeStringHandlingFunctions` query + "cpp/misra/unsafe-string-handling-functions" and + ruleId = "RULE-21-2-2" and + category = "required" + or + query = + // `Query` instance for the `bannedSystemFunction` query + BannedAPIsPackage::bannedSystemFunctionQuery() and + queryId = + // `@id` for the `bannedSystemFunction` query + "cpp/misra/banned-system-function" and + ruleId = "RULE-21-2-3" and + category = "required" + or + query = + // `Query` instance for the `useSmartPtrFactoryFunctions` query + BannedAPIsPackage::useSmartPtrFactoryFunctionsQuery() and + queryId = + // `@id` for the `useSmartPtrFactoryFunctions` query + "cpp/misra/use-smart-ptr-factory-functions" and + ruleId = "RULE-23-11-1" and + category = "advisory" + or + query = + // `Query` instance for the `characterHandlingFunctionRestrictions` query + BannedAPIsPackage::characterHandlingFunctionRestrictionsQuery() and + queryId = + // `@id` for the `characterHandlingFunctionRestrictions` query + "cpp/misra/character-handling-function-restrictions" and + ruleId = "RULE-24-5-1" and + category = "required" + or + query = + // `Query` instance for the `noMemoryFunctionsFromCString` query + BannedAPIsPackage::noMemoryFunctionsFromCStringQuery() and + queryId = + // `@id` for the `noMemoryFunctionsFromCString` query + "cpp/misra/no-memory-functions-from-c-string" and + ruleId = "RULE-24-5-2" and + category = "required" + or + query = + // `Query` instance for the `localeGlobalFunctionNotAllowed` query + BannedAPIsPackage::localeGlobalFunctionNotAllowedQuery() and + queryId = + // `@id` for the `localeGlobalFunctionNotAllowed` query + "cpp/misra/locale-global-function-not-allowed" and + ruleId = "RULE-25-5-1" and + category = "required" +} + +module BannedAPIsPackage { + Query avoidProgramTerminatingFunctionsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `avoidProgramTerminatingFunctions` query + TQueryCPP(TBannedAPIsPackageQuery(TAvoidProgramTerminatingFunctionsQuery())) + } + + Query noVariadicFunctionMacrosQuery() { + //autogenerate `Query` type + result = + // `Query` type for `noVariadicFunctionMacros` query + TQueryCPP(TBannedAPIsPackageQuery(TNoVariadicFunctionMacrosQuery())) + } + + Query noCsetjmpHeaderQuery() { + //autogenerate `Query` type + result = + // `Query` type for `noCsetjmpHeader` query + TQueryCPP(TBannedAPIsPackageQuery(TNoCsetjmpHeaderQuery())) + } + + Query unsafeStringHandlingFunctionsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `unsafeStringHandlingFunctions` query + TQueryCPP(TBannedAPIsPackageQuery(TUnsafeStringHandlingFunctionsQuery())) + } + + Query bannedSystemFunctionQuery() { + //autogenerate `Query` type + result = + // `Query` type for `bannedSystemFunction` query + TQueryCPP(TBannedAPIsPackageQuery(TBannedSystemFunctionQuery())) + } + + Query useSmartPtrFactoryFunctionsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `useSmartPtrFactoryFunctions` query + TQueryCPP(TBannedAPIsPackageQuery(TUseSmartPtrFactoryFunctionsQuery())) + } + + Query characterHandlingFunctionRestrictionsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `characterHandlingFunctionRestrictions` query + TQueryCPP(TBannedAPIsPackageQuery(TCharacterHandlingFunctionRestrictionsQuery())) + } + + Query noMemoryFunctionsFromCStringQuery() { + //autogenerate `Query` type + result = + // `Query` type for `noMemoryFunctionsFromCString` query + TQueryCPP(TBannedAPIsPackageQuery(TNoMemoryFunctionsFromCStringQuery())) + } + + Query localeGlobalFunctionNotAllowedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `localeGlobalFunctionNotAllowed` query + TQueryCPP(TBannedAPIsPackageQuery(TLocaleGlobalFunctionNotAllowedQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll index abd6aeff96..92e1bba574 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -3,6 +3,7 @@ import cpp import codingstandards.cpp.exclusions.RuleMetadata //** Import packages for this language **/ import Allocations +import BannedAPIs import BannedFunctions import BannedLibraries import BannedSyntax @@ -58,6 +59,7 @@ import VirtualFunctions /** The TQuery type representing this language * */ newtype TCPPQuery = TAllocationsPackageQuery(AllocationsQuery q) or + TBannedAPIsPackageQuery(BannedAPIsQuery q) or TBannedFunctionsPackageQuery(BannedFunctionsQuery q) or TBannedLibrariesPackageQuery(BannedLibrariesQuery q) or TBannedSyntaxPackageQuery(BannedSyntaxQuery q) or @@ -113,6 +115,7 @@ newtype TCPPQuery = /** The metadata predicate * */ predicate isQueryMetadata(Query query, string queryId, string ruleId, string category) { isAllocationsQueryMetadata(query, queryId, ruleId, category) or + isBannedAPIsQueryMetadata(query, queryId, ruleId, category) or isBannedFunctionsQueryMetadata(query, queryId, ruleId, category) or isBannedLibrariesQueryMetadata(query, queryId, ruleId, category) or isBannedSyntaxQueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/test/includes/custom-library/custom_abort.h b/cpp/common/test/includes/custom-library/custom_abort.h new file mode 100644 index 0000000000..bab19a8e80 --- /dev/null +++ b/cpp/common/test/includes/custom-library/custom_abort.h @@ -0,0 +1,3 @@ +// Used for RULE-18-5-2 for library aborts +#include +#define LIBRARY_ABORT() std::abort() \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cctype b/cpp/common/test/includes/standard-library/cctype index 98e0805cfd..b45830acbe 100644 --- a/cpp/common/test/includes/standard-library/cctype +++ b/cpp/common/test/includes/standard-library/cctype @@ -1 +1,20 @@ -#include "ctype.h" \ No newline at end of file +#ifndef _GHLIBCPP_CCTYPE +#define _GHLIBCPP_CCTYPE +#include "ctype.h" +namespace std { +using ::isalnum; +using ::isalpha; +using ::isblank; +using ::iscntrl; +using ::isdigit; +using ::isgraph; +using ::islower; +using ::isprint; +using ::ispunct; +using ::isspace; +using ::isupper; +using ::isxdigit; +using ::tolower; +using ::toupper; +} // namespace std +#endif // _GHLIBCPP_CCTYPE diff --git a/cpp/common/test/includes/standard-library/cinttypes b/cpp/common/test/includes/standard-library/cinttypes index 8adb84dd2f..e9f7d45144 100644 --- a/cpp/common/test/includes/standard-library/cinttypes +++ b/cpp/common/test/includes/standard-library/cinttypes @@ -1 +1,12 @@ -#include \ No newline at end of file +#ifndef _GHLIBCPP_CINTTYPES +#define _GHLIBCPP_CINTTYPES +#include "inttypes.h" + +namespace std { +using ::strtoimax; +using ::strtoumax; +using ::wcstoimax; +using ::wcstoumax; +} // namespace std + +#endif // _GHLIBCPP_CINTTYPES \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/clocale b/cpp/common/test/includes/standard-library/clocale index 430c36daa0..8ec16234b8 100644 --- a/cpp/common/test/includes/standard-library/clocale +++ b/cpp/common/test/includes/standard-library/clocale @@ -1,4 +1,5 @@ -#pragma once +#ifndef _GHLIBCPP_CLOCALE +#define _GHLIBCPP_CLOCALE #define NULL 0 #define LC_ALL 0 @@ -15,3 +16,5 @@ using ::lconv; using ::localeconv; using ::setlocale; } // namespace std + +#endif // _GHLIBCPP_CLOCALE \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/csetjmp b/cpp/common/test/includes/standard-library/csetjmp index e69de29bb2..c1f7ceed39 100644 --- a/cpp/common/test/includes/standard-library/csetjmp +++ b/cpp/common/test/includes/standard-library/csetjmp @@ -0,0 +1,12 @@ +#ifndef _GHLIBCPP_CSETJMP +#define _GHLIBCPP_CSETJMP + +#include "setjmp.h" + +// C++ std namespace declarations +namespace std { +using ::jmp_buf; +using ::longjmp; +} // namespace std + +#endif // _GHLIBCPP_CSETJMP \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cstdarg b/cpp/common/test/includes/standard-library/cstdarg index f2b84242a0..6dd883b683 100644 --- a/cpp/common/test/includes/standard-library/cstdarg +++ b/cpp/common/test/includes/standard-library/cstdarg @@ -1,9 +1,9 @@ #pragma once +#ifndef _GHLIBCPP_CSTDARG +#define _GHLIBCPP_CSTDARG +#include "stdarg.h" namespace std { - typedef __builtin_va_list va_list; +using ::va_list; } // namespace std - -#define va_arg(v, p) __builtin_va_arg(v, p) -#define va_end(v) __builtin_va_end(v) -#define va_start(v,l) __builtin_va_start(v,l) \ No newline at end of file +#endif // _GHLIBCPP_CSTDARG \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cstdint b/cpp/common/test/includes/standard-library/cstdint index fedf405ddb..f84fe3e4bb 100644 --- a/cpp/common/test/includes/standard-library/cstdint +++ b/cpp/common/test/includes/standard-library/cstdint @@ -1,6 +1,20 @@ -#ifndef _CPP_CSTDINT -#define _CPP_CSTDINT - -#define MAX_INT -#include -#endif \ No newline at end of file +#ifndef _GHLIBCPP_CSTDINT +#define _GHLIBCPP_CSTDINT +#include "stdint.h" +namespace std { +using ::int16_t; +using ::int32_t; +using ::int64_t; +using ::int8_t; +using ::intmax_t; +using ::uint16_t; +using ::uint32_t; +using ::uint64_t; +using ::uint8_t; +using ::uint_fast16_t; +using ::uint_fast32_t; +using ::uint_fast64_t; +using ::uint_fast8_t; +using ::uintmax_t; +} // namespace std +#endif // _GHLIBCPP_CSTDINT \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cstdint.h b/cpp/common/test/includes/standard-library/cstdint.h deleted file mode 100644 index 6a691637ff..0000000000 --- a/cpp/common/test/includes/standard-library/cstdint.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _GHLIBCPP_CSTDINT -#define _GHLIBCPP_CSTDINT -namespace std { -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef signed short int int16_t; -typedef unsigned short int uint16_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef signed long int int64_t; -typedef unsigned long int uint64_t; -typedef int intmax_t; - -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; -} // namespace std -#endif // _GHLIBCPP_CSTDINT \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cstdlib b/cpp/common/test/includes/standard-library/cstdlib index 23eab7eaca..3b1eefc4a9 100644 --- a/cpp/common/test/includes/standard-library/cstdlib +++ b/cpp/common/test/includes/standard-library/cstdlib @@ -1 +1,27 @@ -#include "cstdlib.h" \ No newline at end of file +#ifndef _GHLIBCPP_CSTDLIB +#define _GHLIBCPP_CSTDLIB +#include "stdlib.h" +namespace std { +using ::_Exit; +using ::abort; +using ::at_quick_exit; +using ::atexit; +using ::atof; +using ::atoi; +using ::atol; +using ::atoll; +using ::exit; +using ::free; +using ::malloc; +using ::quick_exit; +using ::rand; +using ::strtod; +using ::strtof; +using ::strtol; +using ::strtold; +using ::strtoll; +using ::strtoul; +using ::strtoull; +using ::system; +} // namespace std +#endif // _GHLIBCPP_CSTDLIB \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cstdlib.h b/cpp/common/test/includes/standard-library/cstdlib.h deleted file mode 100644 index 4a2d0cd9ee..0000000000 --- a/cpp/common/test/includes/standard-library/cstdlib.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _GHLIBCPP_CSTDLIB -#define _GHLIBCPP_CSTDLIB -#include "stdlib.h" -namespace std { -[[noreturn]] void _Exit(int status) noexcept; -[[noreturn]] void abort(void) noexcept; -[[noreturn]] void quick_exit(int status) noexcept; -extern "C++" int atexit(void (*f)(void)) noexcept; -extern "C++" int at_quick_exit(void (*f)(void)) noexcept; -using ::atof; -using ::atoi; -using ::atol; -using ::atoll; -using ::rand; -} // namespace std -#endif // _GHLIBCPP_CSTDLIB \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cstring b/cpp/common/test/includes/standard-library/cstring index 105e3e4693..1df2276077 100644 --- a/cpp/common/test/includes/standard-library/cstring +++ b/cpp/common/test/includes/standard-library/cstring @@ -1 +1,30 @@ -#include "cstring.h" \ No newline at end of file +#ifndef _GHLIBCPP_CSTRING +#define _GHLIBCPP_CSTRING + +#include + +namespace std { +using ::memcmp; +using ::memcpy; +using ::memmove; +using ::memset; +using ::size_t; +using ::strcat; +using ::strchr; +using ::strcmp; +using ::strcoll; +using ::strcpy; +using ::strcspn; +using ::strerror; +using ::strlen; +using ::strncat; +using ::strncmp; +using ::strncpy; +using ::strpbrk; +using ::strrchr; +using ::strspn; +using ::strstr; +using ::strtok; +using ::strxfrm; +} // namespace std +#endif // _GHLIBCPP_CSTRING \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cstring.h b/cpp/common/test/includes/standard-library/cstring.h deleted file mode 100644 index 2f3ffd393e..0000000000 --- a/cpp/common/test/includes/standard-library/cstring.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _GHLIBCPP_CSTRING -#define _GHLIBCPP_CSTRING - -#include - -namespace std { -using ::memcmp; -using ::memcpy; -using ::memmove; -using ::memset; -using ::size_t; -using ::strcat; -using ::strchr; -using ::strcmp; -using ::strcoll; -using ::strcpy; -using ::strcspn; -using ::strlen; -using ::strncat; -using ::strncmp; -using ::strncpy; -using ::strpbrk; -using ::strrchr; -using ::strspn; -using ::strstr; -using ::strtok; -using ::strxfrm; -} // namespace std -#endif // _GHLIBCPP_CSTRING diff --git a/cpp/common/test/includes/standard-library/ctype.h b/cpp/common/test/includes/standard-library/ctype.h index e9264fd7c6..d7dc851529 100644 --- a/cpp/common/test/includes/standard-library/ctype.h +++ b/cpp/common/test/includes/standard-library/ctype.h @@ -1,8 +1,9 @@ #ifndef _GHLIBCPP_CTYPE #define _GHLIBCPP_CTYPE -namespace std { + extern int isalnum(int); extern int isalpha(int); +extern int isblank(int); extern int iscntrl(int); extern int isdigit(int); extern int islower(int); @@ -14,5 +15,5 @@ extern int isupper(int); extern int isxdigit(int); extern int tolower(int); extern int toupper(int); -} // namespace std + #endif // _GHLIBCPP_CTYPE \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cwchar b/cpp/common/test/includes/standard-library/cwchar index e69de29bb2..a3e70b8d2b 100644 --- a/cpp/common/test/includes/standard-library/cwchar +++ b/cpp/common/test/includes/standard-library/cwchar @@ -0,0 +1,18 @@ +#pragma once +#ifndef _GHLIBCPP_CWCHAR +#define _GHLIBCPP_CWCHAR +#include "wchar.h" + +namespace std { +using ::fgetwc; +using ::fputwc; +using ::wcstod; +using ::wcstof; +using ::wcstol; +using ::wcstold; +using ::wcstoll; +using ::wcstoul; +using ::wcstoull; +} // namespace std + +#endif // _GHLIBCPP_CWCHAR \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cwctype b/cpp/common/test/includes/standard-library/cwctype index e69de29bb2..d2ce5c7e36 100644 --- a/cpp/common/test/includes/standard-library/cwctype +++ b/cpp/common/test/includes/standard-library/cwctype @@ -0,0 +1,38 @@ +#ifndef _GHLIBCPP_CWCTYPE +#define _GHLIBCPP_CWCTYPE +#include "wctype.h" + +namespace std { +// Types +using ::wint_t; +using ::wctype_t; +using ::wctrans_t; + +// Wide character classification functions +using ::iswalnum; +using ::iswalpha; +using ::iswblank; +using ::iswcntrl; +using ::iswdigit; +using ::iswgraph; +using ::iswlower; +using ::iswprint; +using ::iswpunct; +using ::iswspace; +using ::iswupper; +using ::iswxdigit; + +// Wide character conversion functions +using ::towlower; +using ::towupper; + +// Generic wide character classification functions +using ::iswctype; +using ::wctype; + +// Generic wide character mapping functions +using ::towctrans; +using ::wctrans; +} // namespace std + +#endif // _GHLIBCPP_CWCTYPE \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/inttypes.h b/cpp/common/test/includes/standard-library/inttypes.h index d613ea4dcc..2f32726a05 100644 --- a/cpp/common/test/includes/standard-library/inttypes.h +++ b/cpp/common/test/includes/standard-library/inttypes.h @@ -1,11 +1,12 @@ -#pragma once +#ifndef _GHLIBCPP_INTTYPES +#define _GHLIBCPP_INTTYPES +#include -typedef signed char int8_t; -typedef signed short int int16_t; -typedef signed long int int32_t; -typedef signed long long int int64_t; +// String conversion functions +intmax_t strtoimax(const char *str, char **endptr, int base); +uintmax_t strtoumax(const char *str, char **endptr, int base); -typedef unsigned char uint8_t; -typedef unsigned short int uint16_t; -typedef unsigned long int uint32_t; -typedef unsigned long long int uint64_t; \ No newline at end of file +// Wide character versions +intmax_t wcstoimax(const wchar_t *str, wchar_t **endptr, int base); +uintmax_t wcstoumax(const wchar_t *str, wchar_t **endptr, int base); +#endif // _GHLIBCPP_INTTYPES \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/locale b/cpp/common/test/includes/standard-library/locale new file mode 100644 index 0000000000..755c5f6ee1 --- /dev/null +++ b/cpp/common/test/includes/standard-library/locale @@ -0,0 +1,61 @@ + +#ifndef _GHLIBCPP_LOCALE +#define _GHLIBCPP_LOCALE + +#include + +namespace std { + +class locale { +public: + class facet; + class id; + typedef int category; + + static const category none = 0, collate = 0x010, ctype = 0x020, + monetary = 0x040, numeric = 0x080, time = 0x100, + messages = 0x200, + all = collate | ctype | monetary | numeric | time | + messages; + + locale() noexcept; + locale(const locale &other) noexcept; + explicit locale(const char *std_name); + explicit locale(const string &std_name); + locale(const locale &other, const char *std_name, category); + locale(const locale &other, const string &std_name, category); + template locale(const locale &other, Facet *f); + locale(const locale &other, const locale &one, category); + ~locale(); + const locale &operator=(const locale &other) noexcept; + template locale combine(const locale &other) const; + + basic_string name() const; + + bool operator==(const locale &other) const; + bool operator!=(const locale &other) const; + template + bool operator()(const basic_string &s1, + const basic_string &s2) const; + + static locale global(const locale &); + static const locale &classic(); +}; + +template bool isspace(charT c, const locale &loc); +template bool isprint(charT c, const locale &loc); +template bool iscntrl(charT c, const locale &loc); +template bool isupper(charT c, const locale &loc); +template bool islower(charT c, const locale &loc); +template bool isalpha(charT c, const locale &loc); +template bool isdigit(charT c, const locale &loc); +template bool ispunct(charT c, const locale &loc); +template bool isxdigit(charT c, const locale &loc); +template bool isalnum(charT c, const locale &loc); +template bool isgraph(charT c, const locale &loc); +template bool isblank(charT c, const locale &loc); +template charT toupper(charT c, const locale &loc); +template charT tolower(charT c, const locale &loc); +} // namespace std + +#endif // _GHLIBCPP_LOCALE \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/locale.h b/cpp/common/test/includes/standard-library/locale.h index 19a8905531..2501c9c5d5 100644 --- a/cpp/common/test/includes/standard-library/locale.h +++ b/cpp/common/test/includes/standard-library/locale.h @@ -1,38 +1,37 @@ -#ifndef _GHLIBCPP_LOCALE -#define _GHLIBCPP_LOCALE +#ifndef _GHLIBCPP_LOCALE_H +#define _GHLIBCPP_LOCALE_H -#define LC_ALL 6 +#define LC_ALL 6 struct lconv { - char *decimal_point; - char *thousands_sep; - char *grouping; + char *decimal_point; + char *thousands_sep; + char *grouping; - char *int_curr_symbol; - char *currency_symbol; - char *mon_decimal_point; - char *mon_thousands_sep; - char *mon_grouping; - char *positive_sign; - char *negative_sign; - char int_frac_digits; - char frac_digits; - char p_cs_precedes; - char p_sep_by_space; - char n_cs_precedes; - char n_sep_by_space; - char p_sign_posn; - char n_sign_posn; - char int_p_cs_precedes; - char int_p_sep_by_space; - char int_n_cs_precedes; - char int_n_sep_by_space; - char int_p_sign_posn; - char int_n_sign_posn; + char *int_curr_symbol; + char *currency_symbol; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char int_p_cs_precedes; + char int_p_sep_by_space; + char int_n_cs_precedes; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; }; - -char *setlocale (int, const char *); +char *setlocale(int, const char *); struct lconv *localeconv(void); -#endif // _GHLIBCPP_LOCALE \ No newline at end of file +#endif // _GHLIBCPP_LOCALE_H \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/memory.h b/cpp/common/test/includes/standard-library/memory.h index 985ee41602..494f428422 100644 --- a/cpp/common/test/includes/standard-library/memory.h +++ b/cpp/common/test/includes/standard-library/memory.h @@ -23,6 +23,7 @@ class unique_ptr { unique_ptr(T *ptr) {} unique_ptr(const unique_ptr &t) = delete; unique_ptr(unique_ptr &&t) {} + unique_ptr(pointer p, Deleter d) noexcept {} ~unique_ptr() {} T &operator*() const { return *ptr; } T *operator->() const noexcept { return ptr; } @@ -93,8 +94,10 @@ template class shared_ptr : public __shared_ptr { shared_ptr(T *ptr); shared_ptr(const shared_ptr &r) noexcept; template shared_ptr(const shared_ptr &r) noexcept; + template shared_ptr(const shared_ptr &r, T *p) noexcept; shared_ptr(shared_ptr &&r) noexcept; template shared_ptr(shared_ptr &&r) noexcept; + template shared_ptr(T *p, D d); shared_ptr(unique_ptr &&t) {} ~shared_ptr() {} T &operator*() const noexcept; diff --git a/cpp/common/test/includes/standard-library/random.h b/cpp/common/test/includes/standard-library/random.h index 1a2b341226..141b806b62 100644 --- a/cpp/common/test/includes/standard-library/random.h +++ b/cpp/common/test/includes/standard-library/random.h @@ -1,7 +1,7 @@ #ifndef _GHLIBCPP_RANDOM #define _GHLIBCPP_RANDOM -#include "cstdint.h" #include "stddef.h" +#include #include namespace std { diff --git a/cpp/common/test/includes/standard-library/setjmp.h b/cpp/common/test/includes/standard-library/setjmp.h index bb7e4fdc27..3d9ac27eb5 100644 --- a/cpp/common/test/includes/standard-library/setjmp.h +++ b/cpp/common/test/includes/standard-library/setjmp.h @@ -1,14 +1,12 @@ #ifndef _GHLIBCPP_SETJMP #define _GHLIBCPP_SETJMP - -struct __jmp_buf_tag - { - int x; - }; +struct __jmp_buf_tag { + int x; +}; typedef struct __jmp_buf_tag jmp_buf[1]; -void longjmp (struct __jmp_buf_tag __env[1], int __val); -#define setjmp(env) 0 +[[noreturn]] void longjmp(struct __jmp_buf_tag __env[1], int __val); +#define setjmp(env) 0 #endif diff --git a/cpp/common/test/includes/standard-library/stdarg.h b/cpp/common/test/includes/standard-library/stdarg.h index e69de29bb2..cab940168a 100644 --- a/cpp/common/test/includes/standard-library/stdarg.h +++ b/cpp/common/test/includes/standard-library/stdarg.h @@ -0,0 +1,6 @@ + +typedef __builtin_va_list va_list; +#define va_arg(v, p) __builtin_va_arg(v, p) +#define va_end(v) __builtin_va_end(v) +#define va_start(v, l) __builtin_va_start(v, l) +#define va_copy(d, s) __builtin_va_copy(d, s) \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/stdint.h b/cpp/common/test/includes/standard-library/stdint.h index e69de29bb2..ab57461648 100644 --- a/cpp/common/test/includes/standard-library/stdint.h +++ b/cpp/common/test/includes/standard-library/stdint.h @@ -0,0 +1,20 @@ +#ifndef _GHLIBCPP_STDINT +#define _GHLIBCPP_STDINT + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int int16_t; +typedef unsigned short int uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed long int int64_t; +typedef unsigned long int uint64_t; +typedef int intmax_t; +typedef unsigned int uintmax_t; + +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +#endif // _GHLIBCPP_STDINT \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/stdlib.h b/cpp/common/test/includes/standard-library/stdlib.h index 67f1abd694..eb73db0627 100644 --- a/cpp/common/test/includes/standard-library/stdlib.h +++ b/cpp/common/test/includes/standard-library/stdlib.h @@ -8,20 +8,32 @@ void free(void *ptr); void *malloc(size_t size); void *realloc(void *ptr, size_t size); -void abort(); +[[noreturn]] void _Exit(int status) noexcept; +[[noreturn]] void abort(void) noexcept; +[[noreturn]] void quick_exit(int status) noexcept; +extern "C++" int atexit(void (*f)(void)) noexcept; +extern "C++" int at_quick_exit(void (*f)(void)) noexcept; void exit(int code); int system(const char *command); char *getenv(const char *name); -int setenv (const char *, const char *, int); +int setenv(const char *, const char *, int); int atoi(const char *str); long int atol(const char *str); long long int atoll(const char *str); double atof(const char *str); +long int strtol(const char *str, char **endptr, int base); +long long int strtoll(const char *str, char **endptr, int base); +unsigned long int strtoul(const char *str, char **endptr, int base); +unsigned long long int strtoull(const char *str, char **endptr, int base); +double strtod(const char *str, char **endptr); +float strtof(const char *str, char **endptr); +long double strtold(const char *str, char **endptr); + int rand(void); #endif // _GHLIBCPP_STDLIB \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/string.h b/cpp/common/test/includes/standard-library/string.h index d94a186f0e..b4b4d9b121 100644 --- a/cpp/common/test/includes/standard-library/string.h +++ b/cpp/common/test/includes/standard-library/string.h @@ -35,14 +35,13 @@ const char *strstr(const char *str1, const char *str2); char *strstr(char *str1, const char *str2); char *strtok(char *str, const char *delimiters); +char *strerror(int errnum); -char *strdup (const char *); +char *strdup(const char *); void *memcpy(void *dest, const void *src, size_t count); void *memset(void *dest, int ch, size_t count); void *memmove(void *dest, const void *src, size_t count); int memcmp(const void *lhs, const void *rhs, size_t count); -size_t strlen(const char *str); - #endif // _GHLIBCPP_STRINGH \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/string_view b/cpp/common/test/includes/standard-library/string_view new file mode 100644 index 0000000000..7897d2cf78 --- /dev/null +++ b/cpp/common/test/includes/standard-library/string_view @@ -0,0 +1,79 @@ +#pragma once +#ifndef _GHLIBCPP_STRING_VIEW +#define _GHLIBCPP_STRING_VIEW + +#include "stddef.h" + +namespace std { + +template class basic_string_view { +public: + typedef CharT value_type; + typedef const CharT *pointer; + typedef const CharT *const_pointer; + typedef const CharT &reference; + typedef const CharT &const_reference; + typedef const CharT *const_iterator; + typedef const_iterator iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + // Constructors + basic_string_view() noexcept; + basic_string_view(const basic_string_view &) noexcept = default; + basic_string_view(const CharT *s, size_type count); + basic_string_view(const CharT *s); + + // Assignment + basic_string_view &operator=(const basic_string_view &) noexcept = default; + + // Element access + const_reference operator[](size_type pos) const; + const_reference at(size_type pos) const; + const_reference front() const; + const_reference back() const; + const_pointer data() const noexcept; + + // Capacity + size_type size() const noexcept; + size_type length() const noexcept; + size_type max_size() const noexcept; + bool empty() const noexcept; + + // Modifiers + void remove_prefix(size_type n); + void remove_suffix(size_type n); + void swap(basic_string_view &v) noexcept; + + // String operations + size_type copy(CharT *dest, size_type count, size_type pos = 0) const; + basic_string_view substr(size_type pos = 0, size_type len = npos) const; + + // Comparison + int compare(basic_string_view v) const noexcept; + int compare(size_type pos1, size_type n1, basic_string_view v) const; + int compare(const CharT *s) const; + + // Search + size_type find(basic_string_view v, size_type pos = 0) const noexcept; + size_type find(CharT c, size_type pos = 0) const noexcept; + size_type find(const CharT *s, size_type pos, size_type n) const; + size_type find(const CharT *s, size_type pos = 0) const; + + // Constants + static const size_type npos = static_cast(-1); + +private: + const CharT *data_; + size_type size_; +}; + +// Type aliases +typedef basic_string_view string_view; +typedef basic_string_view wstring_view; +typedef basic_string_view u16string_view; +typedef basic_string_view u32string_view; + +} // namespace std + +#endif // _GHLIBCPP_STRING_VIEW diff --git a/cpp/common/test/includes/standard-library/wchar.h b/cpp/common/test/includes/standard-library/wchar.h index e69de29bb2..6c79fb0dec 100644 --- a/cpp/common/test/includes/standard-library/wchar.h +++ b/cpp/common/test/includes/standard-library/wchar.h @@ -0,0 +1,20 @@ +#ifndef _GHLIBCPP_WCHAR +#define _GHLIBCPP_WCHAR + +#include "stddef.h" +#include "wctype.h" + +// Wide character I/O functions +wint_t fgetwc(void *stream); +wint_t fputwc(wchar_t wc, void *stream); + +// Wide character string conversion functions +long wcstol(const wchar_t *str, wchar_t **endptr, int base); +long long wcstoll(const wchar_t *str, wchar_t **endptr, int base); +unsigned long wcstoul(const wchar_t *str, wchar_t **endptr, int base); +unsigned long long wcstoull(const wchar_t *str, wchar_t **endptr, int base); +double wcstod(const wchar_t *str, wchar_t **endptr); +float wcstof(const wchar_t *str, wchar_t **endptr); +long double wcstold(const wchar_t *str, wchar_t **endptr); + +#endif // _GHLIBCPP_WCHAR \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/wctype.h b/cpp/common/test/includes/standard-library/wctype.h index e69de29bb2..d66b63a75c 100644 --- a/cpp/common/test/includes/standard-library/wctype.h +++ b/cpp/common/test/includes/standard-library/wctype.h @@ -0,0 +1,34 @@ +#ifndef _GHLIBCPP_WCTYPE +#define _GHLIBCPP_WCTYPE + +typedef long wint_t; +typedef long wctype_t; +typedef long wctrans_t; + +// Wide character classification functions +extern int iswalnum(wint_t wc); +extern int iswalpha(wint_t wc); +extern int iswblank(wint_t wc); +extern int iswcntrl(wint_t wc); +extern int iswdigit(wint_t wc); +extern int iswgraph(wint_t wc); +extern int iswlower(wint_t wc); +extern int iswprint(wint_t wc); +extern int iswpunct(wint_t wc); +extern int iswspace(wint_t wc); +extern int iswupper(wint_t wc); +extern int iswxdigit(wint_t wc); + +// Wide character conversion functions +extern wint_t towlower(wint_t wc); +extern wint_t towupper(wint_t wc); + +// Generic wide character classification functions +extern int iswctype(wint_t wc, wctype_t desc); +extern wctype_t wctype(const char *property); + +// Generic wide character mapping functions +extern wint_t towctrans(wint_t wc, wctrans_t desc); +extern wctrans_t wctrans(const char *property); + +#endif // _GHLIBCPP_WCTYPE \ No newline at end of file diff --git a/cpp/misra/src/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.ql b/cpp/misra/src/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.ql new file mode 100644 index 0000000000..adafebd44c --- /dev/null +++ b/cpp/misra/src/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.ql @@ -0,0 +1,43 @@ +/** + * @id cpp/misra/avoid-program-terminating-functions + * @name RULE-18-5-2: Program-terminating functions should not be used + * @description Using program-terminating functions like abort, exit, _Exit, quick_exit or terminate + * causes the stack to not be unwound and object destructors to not be called, + * potentially leaving the environment in an undesirable state. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-18-5-2 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.AlertReporting +import codingstandards.cpp.BannedFunctions + +class TerminatingFunction extends Function { + TerminatingFunction() { + this.hasQualifiedName(["", "std"], ["abort", "exit", "_Exit", "quick_exit"]) + or + // std::terminate does not occur in the global namespace. + this.hasQualifiedName("std", "terminate") + } +} + +predicate isInAssertMacroInvocation(BannedFunctions::UseExpr use) { + exists(MacroInvocation mi | + mi.getMacroName() = "assert" and + mi.getAnExpandedElement() = use + ) +} + +from BannedFunctions::UseExpr use +where + not isExcluded(use, BannedAPIsPackage::avoidProgramTerminatingFunctionsQuery()) and + // Exclude the uses in the assert macro + not isInAssertMacroInvocation(use) +select use.getPrimaryElement(), + use.getAction() + " program-terminating function '" + use.getFunctionName() + "'." diff --git a/cpp/misra/src/rules/RULE-21-10-1/NoVariadicFunctionMacros.ql b/cpp/misra/src/rules/RULE-21-10-1/NoVariadicFunctionMacros.ql new file mode 100644 index 0000000000..fbe82d45c6 --- /dev/null +++ b/cpp/misra/src/rules/RULE-21-10-1/NoVariadicFunctionMacros.ql @@ -0,0 +1,57 @@ +/** + * @id cpp/misra/no-variadic-function-macros + * @name RULE-21-10-1: The features of shall not be used + * @description Using features like va_list, va_arg, va_start, va_end and va_copy bypasses + * compiler type checking and leads to undefined behavior when used incorrectly. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-21-10-1 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra + +class VaListType extends Type { + VaListType() { + this.getName() = "va_list" or + this.(SpecifiedType).getBaseType() instanceof VaListType or + this.(TypedefType).getBaseType() instanceof VaListType + } +} + +from Element element, string message +where + not isExcluded(element, BannedAPIsPackage::noVariadicFunctionMacrosQuery()) and + ( + element.(Variable).getType() instanceof VaListType and + ( + if element instanceof Parameter + then + message = + "Declaration of parameter '" + element.(Parameter).getName() + "' of type 'va_list'." + else + message = + "Declaration of variable '" + element.(Variable).getName() + "' of type 'va_list'." + ) + or + element instanceof BuiltInVarArgsStart and + message = "Call to 'va_start'." + or + element instanceof BuiltInVarArgsEnd and + message = "Call to 'va_end'." + or + element instanceof BuiltInVarArg and + message = "Call to 'va_arg'." + or + element instanceof BuiltInVarArgCopy and + message = "Call to 'va_copy'." + or + element.(TypedefType).getBaseType() instanceof VaListType and + message = + "Declaration of typedef '" + element.(TypedefType).getName() + "' aliasing 'va_list' type." + ) +select element, message diff --git a/cpp/misra/src/rules/RULE-21-10-2/NoCsetjmpHeader.ql b/cpp/misra/src/rules/RULE-21-10-2/NoCsetjmpHeader.ql new file mode 100644 index 0000000000..4cfc7770a1 --- /dev/null +++ b/cpp/misra/src/rules/RULE-21-10-2/NoCsetjmpHeader.ql @@ -0,0 +1,53 @@ +/** + * @id cpp/misra/no-csetjmp-header + * @name RULE-21-10-2: The standard header file shall not be used + * @description Using facilities from the header causes undefined behavior by bypassing + * normal function return mechanisms and may result in non-trivial object destruction + * being omitted. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-21-10-2 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.BannedFunctions + +class CSetJmpHeader extends Include { + CSetJmpHeader() { this.getIncludeText().regexpMatch("[<\\\"](csetjmp|setjmp.h)[>\\\"]") } +} + +class JmpBufVariable extends Variable { + JmpBufVariable() { this.getType().(UserType).hasGlobalOrStdName("jmp_buf") } +} + +class LongjmpFunction extends Function { + LongjmpFunction() { this.hasGlobalOrStdName("longjmp") } +} + +class SetjmpMacroInvocation extends MacroInvocation { + SetjmpMacroInvocation() { this.getMacroName() = "setjmp" } +} + +from Element element, string message +where + not isExcluded(element, BannedAPIsPackage::noCsetjmpHeaderQuery()) and + ( + message = "Use of banned header " + element.(CSetJmpHeader).getIncludeText() + "." + or + message = + "Declaration of variable '" + element.(JmpBufVariable).getName() + + "' with banned type 'jmp_buf'." + or + message = + element.(BannedFunctions::Use).getAction() + " banned function '" + + element.(BannedFunctions::Use).getFunctionName() + "'." + or + element instanceof SetjmpMacroInvocation and + message = "Use of banned macro 'setjmp'." + ) +select element, message diff --git a/cpp/misra/src/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.ql b/cpp/misra/src/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.ql new file mode 100644 index 0000000000..ff888c9c22 --- /dev/null +++ b/cpp/misra/src/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.ql @@ -0,0 +1,33 @@ +/** + * @id cpp/misra/unsafe-string-handling-functions + * @name RULE-21-2-2: The string handling functions from , , and shall not be used + * @description Using string handling functions from , , and + * headers may result in buffer overflows or unreliable error detection through errno. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-21-2-2 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.BannedFunctions + +class StringFunction extends Function { + StringFunction() { + this.hasGlobalName([ + "strcat", "strchr", "strcmp", "strcoll", "strcpy", "strcspn", "strerror", "strlen", + "strncat", "strncmp", "strncpy", "strpbrk", "strrchr", "strspn", "strstr", "strtok", + "strxfrm", "strtol", "strtoll", "strtoul", "strtoull", "strtod", "strtof", "strtold", + "fgetwc", "fputwc", "wcstol", "wcstoll", "wcstoul", "wcstoull", "wcstod", "wcstof", + "wcstold", "strtoumax", "strtoimax", "wcstoumax", "wcstoimax" + ]) + } +} + +from BannedFunctions::Use use +where not isExcluded(use, BannedAPIsPackage::unsafeStringHandlingFunctionsQuery()) +select use, use.getAction() + " banned string handling function '" + use.getFunctionName() + "'." diff --git a/cpp/misra/src/rules/RULE-21-2-3/BannedSystemFunction.ql b/cpp/misra/src/rules/RULE-21-2-3/BannedSystemFunction.ql new file mode 100644 index 0000000000..b8cf0788f8 --- /dev/null +++ b/cpp/misra/src/rules/RULE-21-2-3/BannedSystemFunction.ql @@ -0,0 +1,36 @@ +/** + * @id cpp/misra/banned-system-function + * @name RULE-21-2-3: The library function system from shall not be used + * @description Using the system() function from cstdlib or stdlib.h causes undefined behavior and + * potential security vulnerabilities. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-21-2-3 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.BannedFunctions + +class SystemFunction extends Function { + SystemFunction() { this.hasGlobalName("system") or this.hasQualifiedName("std", "system") } +} + +from Element element, string message +where + not isExcluded(element, BannedAPIsPackage::bannedSystemFunctionQuery()) and + ( + element instanceof BannedFunctions::Use and + message = + element.(BannedFunctions::Use).getAction() + " banned function '" + + element.(BannedFunctions::Use).getFunctionName() + "'." + or + element instanceof MacroInvocation and + element.(MacroInvocation).getMacroName() = "system" and + message = "Use of banned macro 'system'." + ) +select element, message diff --git a/cpp/misra/src/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.ql b/cpp/misra/src/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.ql new file mode 100644 index 0000000000..65faa9cfd8 --- /dev/null +++ b/cpp/misra/src/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.ql @@ -0,0 +1,32 @@ +/** + * @id cpp/misra/use-smart-ptr-factory-functions + * @name RULE-23-11-1: The raw pointer constructors of std::shared_ptr and std::unique_ptr should not be used + * @description Using raw pointer constructors of std::shared_ptr and std::unique_ptr instead of + * make_shared/make_unique can lead to memory leaks if exceptions occur during + * construction. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-23-11-1 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra + +from ConstructorCall call, Class smartPtrClass +where + not isExcluded(call, BannedAPIsPackage::useSmartPtrFactoryFunctionsQuery()) and + smartPtrClass = call.getTarget().getDeclaringType() and + ( + smartPtrClass.hasQualifiedName("std", "shared_ptr") or + smartPtrClass.hasQualifiedName("std", "unique_ptr") + ) and + call.getNumberOfArguments() >= 1 and + exists(Type argType | + argType = call.getArgument(0).getType().getUnspecifiedType() and + argType instanceof PointerType + ) +select call, "Use of raw pointer constructor for 'std::" + smartPtrClass.getSimpleName() + "'." diff --git a/cpp/misra/src/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.ql b/cpp/misra/src/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.ql new file mode 100644 index 0000000000..d3dba3c347 --- /dev/null +++ b/cpp/misra/src/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.ql @@ -0,0 +1,44 @@ +/** + * @id cpp/misra/character-handling-function-restrictions + * @name RULE-24-5-1: The character handling functions from and shall not be used + * @description Using character classification and case mapping functions from and + * causes undefined behavior when arguments are not representable as unsigned + * char or not equal to EOF. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-24-5-1 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.BannedFunctions + +class BannedCharacterHandlingFunction extends Function { + BannedCharacterHandlingFunction() { + this.hasGlobalOrStdName([ + "isalnum", "isalpha", "isblank", "iscntrl", "isdigit", "isgraph", "islower", "isprint", + "ispunct", "isspace", "isupper", "isxdigit", "tolower", "toupper", "iswalnum", "iswalpha", + "iswblank", "iswcntrl", "iswctype", "iswdigit", "iswgraph", "iswlower", "iswprint", + "iswpunct", "iswspace", "iswupper", "iswxdigit", "towctrans", "towlower", "towupper", + "wctrans", "wctype" + ]) and + // Exclude the functions which pass a reference to a std::locale as the second parameter + not this.getParameter(1) + .getType() + .getUnspecifiedType() + .(ReferenceType) + .getBaseType() + .(UserType) + .hasQualifiedName("std", "locale") + } +} + +from BannedFunctions::Use use +where not isExcluded(use, BannedAPIsPackage::characterHandlingFunctionRestrictionsQuery()) +select use, + use.getAction() + " banned character handling function '" + use.getFunctionName() + + "' from or ." diff --git a/cpp/misra/src/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.ql b/cpp/misra/src/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.ql new file mode 100644 index 0000000000..17bca5c0eb --- /dev/null +++ b/cpp/misra/src/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.ql @@ -0,0 +1,26 @@ +/** + * @id cpp/misra/no-memory-functions-from-c-string + * @name RULE-24-5-2: The C++ Standard Library functions memcpy, memmove and memcmp from shall not be used + * @description Using memcpy, memmove or memcmp from can result in undefined behavior due + * to overlapping memory, non-trivially copyable objects, or unequal comparison of + * logically equal objects. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-24-5-2 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.BannedFunctions + +class BannedMemoryFunction extends Function { + BannedMemoryFunction() { this.hasGlobalOrStdName(["memcpy", "memmove", "memcmp"]) } +} + +from BannedFunctions::Use use +where not isExcluded(use, BannedAPIsPackage::noMemoryFunctionsFromCStringQuery()) +select use, use.getAction() + " banned function '" + use.getFunctionName() + "' from ." diff --git a/cpp/misra/src/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.ql b/cpp/misra/src/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.ql new file mode 100644 index 0000000000..5072da9789 --- /dev/null +++ b/cpp/misra/src/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.ql @@ -0,0 +1,28 @@ +/** + * @id cpp/misra/locale-global-function-not-allowed + * @name RULE-25-5-1: The setlocale and std::locale::global functions shall not be called + * @description Calling setlocale or std::locale::global functions can introduce data races with + * functions that use the locale, leading to undefined behavior. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-25-5-1 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.BannedFunctions + +class BannedLocaleFunction extends Function { + BannedLocaleFunction() { + this.hasGlobalOrStdName("setlocale") or + this.hasQualifiedName("std", "locale", "global") + } +} + +from BannedFunctions::Use use +where not isExcluded(use, BannedAPIsPackage::localeGlobalFunctionNotAllowedQuery()) +select use, use.getAction() + " banned function '" + use.getFunctionName() + "' from ." diff --git a/cpp/misra/test/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.expected b/cpp/misra/test/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.expected new file mode 100644 index 0000000000..4f0a79dcb3 --- /dev/null +++ b/cpp/misra/test/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.expected @@ -0,0 +1,31 @@ +| test.cpp:8:3:8:7 | call to abort | Call to program-terminating function 'abort'. | +| test.cpp:9:3:9:6 | call to exit | Call to program-terminating function 'exit'. | +| test.cpp:10:3:10:7 | call to _Exit | Call to program-terminating function '_Exit'. | +| test.cpp:11:3:11:12 | call to quick_exit | Call to program-terminating function 'quick_exit'. | +| test.cpp:16:3:16:12 | call to abort | Call to program-terminating function 'abort'. | +| test.cpp:17:3:17:11 | call to exit | Call to program-terminating function 'exit'. | +| test.cpp:18:3:18:12 | call to _Exit | Call to program-terminating function '_Exit'. | +| test.cpp:19:3:19:17 | call to quick_exit | Call to program-terminating function 'quick_exit'. | +| test.cpp:20:3:20:16 | call to terminate | Call to program-terminating function 'terminate'. | +| test.cpp:25:14:25:18 | abort | Address taken for program-terminating function 'abort'. | +| test.cpp:26:14:26:17 | exit | Address taken for program-terminating function 'exit'. | +| test.cpp:27:14:27:18 | _Exit | Address taken for program-terminating function '_Exit'. | +| test.cpp:28:14:28:23 | quick_exit | Address taken for program-terminating function 'quick_exit'. | +| test.cpp:29:14:29:23 | abort | Address taken for program-terminating function 'abort'. | +| test.cpp:30:14:30:22 | exit | Address taken for program-terminating function 'exit'. | +| test.cpp:31:14:31:23 | _Exit | Address taken for program-terminating function '_Exit'. | +| test.cpp:32:14:32:28 | quick_exit | Address taken for program-terminating function 'quick_exit'. | +| test.cpp:33:14:33:27 | terminate | Address taken for program-terminating function 'terminate'. | +| test.cpp:38:18:38:22 | abort | Address taken for program-terminating function 'abort'. | +| test.cpp:39:21:39:24 | exit | Address taken for program-terminating function 'exit'. | +| test.cpp:40:21:40:25 | _Exit | Address taken for program-terminating function '_Exit'. | +| test.cpp:41:21:41:30 | quick_exit | Address taken for program-terminating function 'quick_exit'. | +| test.cpp:42:18:42:27 | abort | Address taken for program-terminating function 'abort'. | +| test.cpp:43:21:43:29 | exit | Address taken for program-terminating function 'exit'. | +| test.cpp:44:21:44:30 | _Exit | Address taken for program-terminating function '_Exit'. | +| test.cpp:45:21:45:35 | quick_exit | Address taken for program-terminating function 'quick_exit'. | +| test.cpp:46:18:46:31 | terminate | Address taken for program-terminating function 'terminate'. | +| test.cpp:68:1:68:33 | #define CALL_ABORT() std::abort() | Call to program-terminating function 'abort'. | +| test.cpp:69:1:69:33 | #define CALL_EXIT(x) std::exit(x) | Call to program-terminating function 'exit'. | +| test.cpp:70:1:70:41 | #define CALL_TERMINATE() std::terminate() | Call to program-terminating function 'terminate'. | +| test.cpp:77:3:77:17 | call to abort | Call to program-terminating function 'abort'. | diff --git a/cpp/misra/test/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.qlref b/cpp/misra/test/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.qlref new file mode 100644 index 0000000000..afb81410c4 --- /dev/null +++ b/cpp/misra/test/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.qlref @@ -0,0 +1 @@ +rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-18-5-2/test.cpp b/cpp/misra/test/rules/RULE-18-5-2/test.cpp new file mode 100644 index 0000000000..d2e2cca386 --- /dev/null +++ b/cpp/misra/test/rules/RULE-18-5-2/test.cpp @@ -0,0 +1,79 @@ +#include "custom_abort.h" +#include +#include +#include + +void test_direct_calls_to_terminating_functions() { + // Direct calls to program-terminating functions + abort(); // NON_COMPLIANT + exit(0); // NON_COMPLIANT + _Exit(1); // NON_COMPLIANT + quick_exit(2); // NON_COMPLIANT +} + +void test_std_namespace_calls() { + // Calls to functions in std namespace + std::abort(); // NON_COMPLIANT + std::exit(0); // NON_COMPLIANT + std::_Exit(1); // NON_COMPLIANT + std::quick_exit(2); // NON_COMPLIANT + std::terminate(); // NON_COMPLIANT +} + +void test_taking_addresses_of_terminating_functions() { + // Taking addresses of program-terminating functions + auto l1 = &abort; // NON_COMPLIANT + auto l2 = &exit; // NON_COMPLIANT + auto l3 = &_Exit; // NON_COMPLIANT + auto l4 = &quick_exit; // NON_COMPLIANT + auto l5 = &std::abort; // NON_COMPLIANT + auto l6 = &std::exit; // NON_COMPLIANT + auto l7 = &std::_Exit; // NON_COMPLIANT + auto l8 = &std::quick_exit; // NON_COMPLIANT + auto l9 = &std::terminate; // NON_COMPLIANT +} + +void test_function_pointers_to_terminating_functions() { + // Function pointers to program-terminating functions + void (*l1)() = abort; // NON_COMPLIANT + void (*l2)(int) = exit; // NON_COMPLIANT + void (*l3)(int) = _Exit; // NON_COMPLIANT + void (*l4)(int) = quick_exit; // NON_COMPLIANT + void (*l5)() = std::abort; // NON_COMPLIANT + void (*l6)(int) = std::exit; // NON_COMPLIANT + void (*l7)(int) = std::_Exit; // NON_COMPLIANT + void (*l8)(int) = std::quick_exit; // NON_COMPLIANT + void (*l9)() = std::terminate; // NON_COMPLIANT +} + +void test_assert_macro_exception() { + // The call to abort via assert macro is compliant by exception + assert(true); // COMPLIANT + assert(1 == 1); // COMPLIANT +} + +void f1() { + // Valid alternative: normal function return + return; // COMPLIANT +} + +void test_compliant_alternatives() { + // Using normal control flow instead of terminating functions + f1(); // COMPLIANT + + // Using exceptions for error handling + throw std::runtime_error("error"); // COMPLIANT +} + +#define CALL_ABORT() std::abort() // NON_COMPLIANT +#define CALL_EXIT(x) std::exit(x) // NON_COMPLIANT +#define CALL_TERMINATE() std::terminate() // NON_COMPLIANT + +void test_macro_expansion_with_terminating_functions() { + // Macro expansions containing terminating functions + CALL_ABORT(); // reported at the definition site + CALL_EXIT(1); // reported at the definition site + CALL_TERMINATE(); // reported at the definition site + LIBRARY_ABORT(); // NON_COMPLIANT - macro not defined by user, so flagged at + // the call site +} \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-10-1/NoVariadicFunctionMacros.expected b/cpp/misra/test/rules/RULE-21-10-1/NoVariadicFunctionMacros.expected new file mode 100644 index 0000000000..bb52ced03a --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-10-1/NoVariadicFunctionMacros.expected @@ -0,0 +1,28 @@ +| test.cpp:5:11:5:12 | l1 | Declaration of variable 'l1' of type 'va_list'. | +| test.cpp:9:11:9:12 | l2 | Declaration of variable 'l2' of type 'va_list'. | +| test.cpp:10:3:10:18 | __builtin_va_start | Call to 'va_start'. | +| test.cpp:11:3:11:12 | __builtin_va_end | Call to 'va_end'. | +| test.cpp:15:11:15:12 | l2 | Declaration of variable 'l2' of type 'va_list'. | +| test.cpp:16:3:16:18 | __builtin_va_start | Call to 'va_start'. | +| test.cpp:17:21:17:44 | __builtin_va_arg | Call to 'va_arg'. | +| test.cpp:18:3:18:12 | __builtin_va_end | Call to 'va_end'. | +| test.cpp:22:11:22:12 | l2 | Declaration of variable 'l2' of type 'va_list'. | +| test.cpp:23:3:23:18 | __builtin_va_start | Call to 'va_start'. | +| test.cpp:24:3:24:12 | __builtin_va_end | Call to 'va_end'. | +| test.cpp:28:11:28:12 | l2 | Declaration of variable 'l2' of type 'va_list'. | +| test.cpp:28:15:28:16 | l3 | Declaration of variable 'l3' of type 'va_list'. | +| test.cpp:29:3:29:18 | __builtin_va_start | Call to 'va_start'. | +| test.cpp:30:3:30:17 | __builtin_va_copy | Call to 'va_copy'. | +| test.cpp:31:3:31:12 | __builtin_va_end | Call to 'va_end'. | +| test.cpp:32:3:32:12 | __builtin_va_end | Call to 'va_end'. | +| test.cpp:35:37:35:38 | l1 | Declaration of parameter 'l1' of type 'va_list'. | +| test.cpp:36:15:36:32 | __builtin_va_arg | Call to 'va_arg'. | +| test.cpp:40:11:40:12 | l2 | Declaration of variable 'l2' of type 'va_list'. | +| test.cpp:41:3:41:18 | __builtin_va_start | Call to 'va_start'. | +| test.cpp:42:21:42:44 | __builtin_va_arg | Call to 'va_arg'. | +| test.cpp:43:15:43:32 | __builtin_va_arg | Call to 'va_arg'. | +| test.cpp:44:3:44:12 | __builtin_va_end | Call to 'va_end'. | +| test.cpp:55:17:55:29 | va_list_alias | Declaration of typedef 'va_list_alias' aliasing 'va_list' type. | +| test.cpp:56:17:56:25 | SOME_TYPE | Declaration of typedef 'SOME_TYPE' aliasing 'va_list' type. | +| test.cpp:58:17:58:18 | l1 | Declaration of variable 'l1' of type 'va_list'. | +| test.cpp:59:13:59:14 | l2 | Declaration of variable 'l2' of type 'va_list'. | diff --git a/cpp/misra/test/rules/RULE-21-10-1/NoVariadicFunctionMacros.qlref b/cpp/misra/test/rules/RULE-21-10-1/NoVariadicFunctionMacros.qlref new file mode 100644 index 0000000000..7106c2aa2d --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-10-1/NoVariadicFunctionMacros.qlref @@ -0,0 +1 @@ +rules/RULE-21-10-1/NoVariadicFunctionMacros.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-10-1/test.cpp b/cpp/misra/test/rules/RULE-21-10-1/test.cpp new file mode 100644 index 0000000000..1ff0793e05 --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-10-1/test.cpp @@ -0,0 +1,60 @@ +#include +#include + +void test_va_list_declaration() { + va_list l1; // NON_COMPLIANT +} + +void test_va_start_usage(std::int32_t l1, ...) { + va_list l2; // NON_COMPLIANT + va_start(l2, l1); // NON_COMPLIANT + va_end(l2); // NON_COMPLIANT +} + +void test_va_arg_usage(std::int32_t l1, ...) { + va_list l2; // NON_COMPLIANT + va_start(l2, l1); // NON_COMPLIANT + std::int32_t l3 = va_arg(l2, std::int32_t); // NON_COMPLIANT + va_end(l2); // NON_COMPLIANT +} + +void test_va_end_usage(std::int32_t l1, ...) { + va_list l2; // NON_COMPLIANT + va_start(l2, l1); // NON_COMPLIANT + va_end(l2); // NON_COMPLIANT +} + +void test_va_copy_usage(std::int32_t l1, ...) { + va_list l2, l3; // NON_COMPLIANT + va_start(l2, l1); // NON_COMPLIANT + va_copy(l3, l2); // NON_COMPLIANT + va_end(l3); // NON_COMPLIANT + va_end(l2); // NON_COMPLIANT +} + +void test_va_list_parameter(va_list l1) { // NON_COMPLIANT + double l2 = va_arg(l1, double); // NON_COMPLIANT +} + +void test_multiple_va_arg_calls(std::int32_t l1, ...) { + va_list l2; // NON_COMPLIANT + va_start(l2, l1); // NON_COMPLIANT + std::int32_t l3 = va_arg(l2, std::int32_t); // NON_COMPLIANT + double l4 = va_arg(l2, double); // NON_COMPLIANT + va_end(l2); // NON_COMPLIANT +} + +void test_variadic_function_declaration(std::int16_t l1, ...) { + // Function declaration with ellipsis is compliant +} + +void test_variadic_function_call() { + test_variadic_function_declaration(1, 2.0, 3.0); // COMPLIANT +} + +typedef va_list va_list_alias; // NON_COMPLIANT +typedef va_list SOME_TYPE; // NON_COMPLIANT +void test_va_list_alias() { + va_list_alias l1; // NON_COMPLIANT + SOME_TYPE l2; // NON_COMPLIANT +} \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-10-2/NoCsetjmpHeader.expected b/cpp/misra/test/rules/RULE-21-10-2/NoCsetjmpHeader.expected new file mode 100644 index 0000000000..6ac8e41484 --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-10-2/NoCsetjmpHeader.expected @@ -0,0 +1,14 @@ +| test.cpp:1:1:1:18 | #include "csetjmp" | Use of banned header "csetjmp". | +| test.cpp:2:1:2:19 | #include "setjmp.h" | Use of banned header "setjmp.h". | +| test.cpp:3:1:3:18 | #include | Use of banned header . | +| test.cpp:4:1:4:19 | #include | Use of banned header . | +| test.cpp:8:9:8:10 | g1 | Declaration of variable 'g1' with banned type 'jmp_buf'. | +| test.cpp:9:14:9:15 | g2 | Declaration of variable 'g2' with banned type 'jmp_buf'. | +| test.cpp:12:11:12:12 | l1 | Declaration of variable 'l1' with banned type 'jmp_buf'. | +| test.cpp:13:7:13:16 | setjmp(env) | Use of banned macro 'setjmp'. | +| test.cpp:14:5:14:11 | call to longjmp | Call to banned function 'longjmp'. | +| test.cpp:19:16:19:17 | l1 | Declaration of variable 'l1' with banned type 'jmp_buf'. | +| test.cpp:20:7:20:16 | setjmp(env) | Use of banned macro 'setjmp'. | +| test.cpp:21:5:21:16 | call to longjmp | Call to banned function 'longjmp'. | +| test.cpp:26:11:26:12 | l1 | Declaration of variable 'l1' with banned type 'jmp_buf'. | +| test.cpp:27:16:27:17 | l2 | Declaration of variable 'l2' with banned type 'jmp_buf'. | diff --git a/cpp/misra/test/rules/RULE-21-10-2/NoCsetjmpHeader.qlref b/cpp/misra/test/rules/RULE-21-10-2/NoCsetjmpHeader.qlref new file mode 100644 index 0000000000..8e0712349f --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-10-2/NoCsetjmpHeader.qlref @@ -0,0 +1 @@ +rules/RULE-21-10-2/NoCsetjmpHeader.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-10-2/test.cpp b/cpp/misra/test/rules/RULE-21-10-2/test.cpp new file mode 100644 index 0000000000..8fbed19530 --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-10-2/test.cpp @@ -0,0 +1,38 @@ +#include "csetjmp" // NON_COMPLIANT +#include "setjmp.h" // NON_COMPLIANT +#include // NON_COMPLIANT +#include // NON_COMPLIANT +#include + +// Global variables for testing +jmp_buf g1; // NON_COMPLIANT +std::jmp_buf g2; // NON_COMPLIANT + +void test_setjmp_usage() { + jmp_buf l1; // NON_COMPLIANT + if (setjmp(l1) == 0) { // NON_COMPLIANT + longjmp(l1, 1); // NON_COMPLIANT + } +} + +void test_std_setjmp_usage() { + std::jmp_buf l1; // NON_COMPLIANT + if (setjmp(l1) == 0) { // NON_COMPLIANT + std::longjmp(l1, 1); // NON_COMPLIANT + } +} + +void test_jmp_buf_declaration() { + jmp_buf l1; // NON_COMPLIANT + std::jmp_buf l2; // NON_COMPLIANT +} + +void test_compliant_alternative() { + // Using structured exception handling or other alternatives + // instead of setjmp/longjmp + try { + throw std::runtime_error("error"); + } catch (const std::runtime_error &) { // COMPLIANT + // Handle error properly + } +} \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.expected b/cpp/misra/test/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.expected new file mode 100644 index 0000000000..fc0efb103b --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.expected @@ -0,0 +1,222 @@ +| test.cpp:16:3:16:8 | call to strcat | Call to banned string handling function 'strcat'. | +| test.cpp:17:3:17:8 | call to strchr | Call to banned string handling function 'strchr'. | +| test.cpp:18:3:18:8 | call to strcmp | Call to banned string handling function 'strcmp'. | +| test.cpp:19:3:19:9 | call to strcoll | Call to banned string handling function 'strcoll'. | +| test.cpp:20:3:20:8 | call to strcpy | Call to banned string handling function 'strcpy'. | +| test.cpp:21:3:21:9 | call to strcspn | Call to banned string handling function 'strcspn'. | +| test.cpp:22:3:22:10 | call to strerror | Call to banned string handling function 'strerror'. | +| test.cpp:23:3:23:8 | call to strlen | Call to banned string handling function 'strlen'. | +| test.cpp:24:3:24:9 | call to strncat | Call to banned string handling function 'strncat'. | +| test.cpp:25:3:25:9 | call to strncmp | Call to banned string handling function 'strncmp'. | +| test.cpp:26:3:26:9 | call to strncpy | Call to banned string handling function 'strncpy'. | +| test.cpp:27:3:27:9 | call to strpbrk | Call to banned string handling function 'strpbrk'. | +| test.cpp:28:3:28:9 | call to strrchr | Call to banned string handling function 'strrchr'. | +| test.cpp:29:3:29:8 | call to strspn | Call to banned string handling function 'strspn'. | +| test.cpp:30:3:30:8 | call to strstr | Call to banned string handling function 'strstr'. | +| test.cpp:31:3:31:8 | call to strtok | Call to banned string handling function 'strtok'. | +| test.cpp:32:3:32:9 | call to strxfrm | Call to banned string handling function 'strxfrm'. | +| test.cpp:39:3:39:8 | call to strtol | Call to banned string handling function 'strtol'. | +| test.cpp:40:3:40:9 | call to strtoll | Call to banned string handling function 'strtoll'. | +| test.cpp:41:3:41:9 | call to strtoul | Call to banned string handling function 'strtoul'. | +| test.cpp:42:3:42:10 | call to strtoull | Call to banned string handling function 'strtoull'. | +| test.cpp:43:3:43:8 | call to strtod | Call to banned string handling function 'strtod'. | +| test.cpp:44:3:44:8 | call to strtof | Call to banned string handling function 'strtof'. | +| test.cpp:45:3:45:9 | call to strtold | Call to banned string handling function 'strtold'. | +| test.cpp:54:3:54:8 | call to fgetwc | Call to banned string handling function 'fgetwc'. | +| test.cpp:55:3:55:8 | call to fputwc | Call to banned string handling function 'fputwc'. | +| test.cpp:56:3:56:8 | call to wcstol | Call to banned string handling function 'wcstol'. | +| test.cpp:57:3:57:9 | call to wcstoll | Call to banned string handling function 'wcstoll'. | +| test.cpp:58:3:58:9 | call to wcstoul | Call to banned string handling function 'wcstoul'. | +| test.cpp:59:3:59:10 | call to wcstoull | Call to banned string handling function 'wcstoull'. | +| test.cpp:60:3:60:8 | call to wcstod | Call to banned string handling function 'wcstod'. | +| test.cpp:61:3:61:8 | call to wcstof | Call to banned string handling function 'wcstof'. | +| test.cpp:62:3:62:9 | call to wcstold | Call to banned string handling function 'wcstold'. | +| test.cpp:71:3:71:11 | call to strtoumax | Call to banned string handling function 'strtoumax'. | +| test.cpp:72:3:72:11 | call to strtoimax | Call to banned string handling function 'strtoimax'. | +| test.cpp:73:3:73:11 | call to wcstoumax | Call to banned string handling function 'wcstoumax'. | +| test.cpp:74:3:74:11 | call to wcstoimax | Call to banned string handling function 'wcstoimax'. | +| test.cpp:78:40:78:45 | strcat | Address taken for banned string handling function 'strcat'. | +| test.cpp:79:39:79:44 | strcat | Address taken for banned string handling function 'strcat'. | +| test.cpp:80:42:80:48 | strchr | Address taken for banned string handling function 'strchr'. | +| test.cpp:81:42:81:47 | strchr | Address taken for banned string handling function 'strchr'. | +| test.cpp:82:44:82:49 | strcmp | Address taken for banned string handling function 'strcmp'. | +| test.cpp:83:43:83:48 | strcmp | Address taken for banned string handling function 'strcmp'. | +| test.cpp:84:44:84:50 | strcoll | Address taken for banned string handling function 'strcoll'. | +| test.cpp:85:43:85:49 | strcoll | Address taken for banned string handling function 'strcoll'. | +| test.cpp:86:40:86:45 | strcpy | Address taken for banned string handling function 'strcpy'. | +| test.cpp:87:40:87:45 | strcpy | Address taken for banned string handling function 'strcpy'. | +| test.cpp:88:48:88:54 | strcspn | Address taken for banned string handling function 'strcspn'. | +| test.cpp:89:47:89:53 | strcspn | Address taken for banned string handling function 'strcspn'. | +| test.cpp:90:24:90:31 | strerror | Address taken for banned string handling function 'strerror'. | +| test.cpp:91:23:91:30 | strerror | Address taken for banned string handling function 'strerror'. | +| test.cpp:92:34:92:39 | strlen | Address taken for banned string handling function 'strlen'. | +| test.cpp:93:33:93:38 | strlen | Address taken for banned string handling function 'strlen'. | +| test.cpp:94:49:94:55 | strncat | Address taken for banned string handling function 'strncat'. | +| test.cpp:95:48:95:54 | strncat | Address taken for banned string handling function 'strncat'. | +| test.cpp:96:53:96:59 | strncmp | Address taken for banned string handling function 'strncmp'. | +| test.cpp:97:52:97:58 | strncmp | Address taken for banned string handling function 'strncmp'. | +| test.cpp:98:49:98:55 | strncpy | Address taken for banned string handling function 'strncpy'. | +| test.cpp:99:48:99:54 | strncpy | Address taken for banned string handling function 'strncpy'. | +| test.cpp:100:52:100:59 | strpbrk | Address taken for banned string handling function 'strpbrk'. | +| test.cpp:101:52:101:58 | strpbrk | Address taken for banned string handling function 'strpbrk'. | +| test.cpp:102:43:102:50 | strrchr | Address taken for banned string handling function 'strrchr'. | +| test.cpp:103:43:103:49 | strrchr | Address taken for banned string handling function 'strrchr'. | +| test.cpp:104:48:104:53 | strspn | Address taken for banned string handling function 'strspn'. | +| test.cpp:105:47:105:52 | strspn | Address taken for banned string handling function 'strspn'. | +| test.cpp:106:52:106:58 | strstr | Address taken for banned string handling function 'strstr'. | +| test.cpp:107:52:107:57 | strstr | Address taken for banned string handling function 'strstr'. | +| test.cpp:108:41:108:46 | strtok | Address taken for banned string handling function 'strtok'. | +| test.cpp:109:40:109:45 | strtok | Address taken for banned string handling function 'strtok'. | +| test.cpp:110:50:110:56 | strxfrm | Address taken for banned string handling function 'strxfrm'. | +| test.cpp:111:49:111:55 | strxfrm | Address taken for banned string handling function 'strxfrm'. | +| test.cpp:115:45:115:50 | strtol | Address taken for banned string handling function 'strtol'. | +| test.cpp:116:44:116:49 | strtol | Address taken for banned string handling function 'strtol'. | +| test.cpp:117:50:117:56 | strtoll | Address taken for banned string handling function 'strtoll'. | +| test.cpp:118:49:118:55 | strtoll | Address taken for banned string handling function 'strtoll'. | +| test.cpp:119:54:119:60 | strtoul | Address taken for banned string handling function 'strtoul'. | +| test.cpp:120:53:120:59 | strtoul | Address taken for banned string handling function 'strtoul'. | +| test.cpp:122:8:122:15 | strtoull | Address taken for banned string handling function 'strtoull'. | +| test.cpp:124:7:124:14 | strtoull | Address taken for banned string handling function 'strtoull'. | +| test.cpp:125:42:125:47 | strtod | Address taken for banned string handling function 'strtod'. | +| test.cpp:126:42:126:47 | strtod | Address taken for banned string handling function 'strtod'. | +| test.cpp:127:42:127:47 | strtof | Address taken for banned string handling function 'strtof'. | +| test.cpp:128:41:128:46 | strtof | Address taken for banned string handling function 'strtof'. | +| test.cpp:129:48:129:54 | strtold | Address taken for banned string handling function 'strtold'. | +| test.cpp:130:47:130:53 | strtold | Address taken for banned string handling function 'strtold'. | +| test.cpp:134:27:134:32 | fgetwc | Address taken for banned string handling function 'fgetwc'. | +| test.cpp:135:26:135:31 | fgetwc | Address taken for banned string handling function 'fgetwc'. | +| test.cpp:136:36:136:41 | fputwc | Address taken for banned string handling function 'fputwc'. | +| test.cpp:137:35:137:40 | fputwc | Address taken for banned string handling function 'fputwc'. | +| test.cpp:138:51:138:56 | wcstol | Address taken for banned string handling function 'wcstol'. | +| test.cpp:139:50:139:55 | wcstol | Address taken for banned string handling function 'wcstol'. | +| test.cpp:140:56:140:62 | wcstoll | Address taken for banned string handling function 'wcstoll'. | +| test.cpp:141:55:141:61 | wcstoll | Address taken for banned string handling function 'wcstoll'. | +| test.cpp:143:8:143:14 | wcstoul | Address taken for banned string handling function 'wcstoul'. | +| test.cpp:145:7:145:13 | wcstoul | Address taken for banned string handling function 'wcstoul'. | +| test.cpp:147:8:147:15 | wcstoull | Address taken for banned string handling function 'wcstoull'. | +| test.cpp:149:7:149:14 | wcstoull | Address taken for banned string handling function 'wcstoull'. | +| test.cpp:150:49:150:54 | wcstod | Address taken for banned string handling function 'wcstod'. | +| test.cpp:151:48:151:53 | wcstod | Address taken for banned string handling function 'wcstod'. | +| test.cpp:152:48:152:53 | wcstof | Address taken for banned string handling function 'wcstof'. | +| test.cpp:153:47:153:52 | wcstof | Address taken for banned string handling function 'wcstof'. | +| test.cpp:154:54:154:60 | wcstold | Address taken for banned string handling function 'wcstold'. | +| test.cpp:155:53:155:59 | wcstold | Address taken for banned string handling function 'wcstold'. | +| test.cpp:159:50:159:58 | strtoumax | Address taken for banned string handling function 'strtoumax'. | +| test.cpp:160:49:160:57 | strtoumax | Address taken for banned string handling function 'strtoumax'. | +| test.cpp:161:49:161:57 | strtoimax | Address taken for banned string handling function 'strtoimax'. | +| test.cpp:162:48:162:56 | strtoimax | Address taken for banned string handling function 'strtoimax'. | +| test.cpp:164:8:164:16 | wcstoumax | Address taken for banned string handling function 'wcstoumax'. | +| test.cpp:166:7:166:15 | wcstoumax | Address taken for banned string handling function 'wcstoumax'. | +| test.cpp:168:8:168:16 | wcstoimax | Address taken for banned string handling function 'wcstoimax'. | +| test.cpp:169:54:169:62 | wcstoimax | Address taken for banned string handling function 'wcstoimax'. | +| test.cpp:177:3:177:13 | call to strcat | Call to banned string handling function 'strcat'. | +| test.cpp:178:3:178:13 | call to strchr | Call to banned string handling function 'strchr'. | +| test.cpp:179:3:179:13 | call to strcmp | Call to banned string handling function 'strcmp'. | +| test.cpp:180:3:180:14 | call to strcoll | Call to banned string handling function 'strcoll'. | +| test.cpp:181:3:181:13 | call to strcpy | Call to banned string handling function 'strcpy'. | +| test.cpp:182:3:182:14 | call to strcspn | Call to banned string handling function 'strcspn'. | +| test.cpp:183:3:183:15 | call to strerror | Call to banned string handling function 'strerror'. | +| test.cpp:184:3:184:13 | call to strlen | Call to banned string handling function 'strlen'. | +| test.cpp:185:3:185:14 | call to strncat | Call to banned string handling function 'strncat'. | +| test.cpp:186:3:186:14 | call to strncmp | Call to banned string handling function 'strncmp'. | +| test.cpp:187:3:187:14 | call to strncpy | Call to banned string handling function 'strncpy'. | +| test.cpp:188:3:188:14 | call to strpbrk | Call to banned string handling function 'strpbrk'. | +| test.cpp:189:3:189:14 | call to strrchr | Call to banned string handling function 'strrchr'. | +| test.cpp:190:3:190:13 | call to strspn | Call to banned string handling function 'strspn'. | +| test.cpp:191:3:191:13 | call to strstr | Call to banned string handling function 'strstr'. | +| test.cpp:192:3:192:13 | call to strtok | Call to banned string handling function 'strtok'. | +| test.cpp:193:3:193:14 | call to strxfrm | Call to banned string handling function 'strxfrm'. | +| test.cpp:200:3:200:13 | call to strtol | Call to banned string handling function 'strtol'. | +| test.cpp:201:3:201:14 | call to strtoll | Call to banned string handling function 'strtoll'. | +| test.cpp:202:3:202:14 | call to strtoul | Call to banned string handling function 'strtoul'. | +| test.cpp:203:3:203:15 | call to strtoull | Call to banned string handling function 'strtoull'. | +| test.cpp:204:3:204:13 | call to strtod | Call to banned string handling function 'strtod'. | +| test.cpp:205:3:205:13 | call to strtof | Call to banned string handling function 'strtof'. | +| test.cpp:206:3:206:14 | call to strtold | Call to banned string handling function 'strtold'. | +| test.cpp:215:3:215:13 | call to fgetwc | Call to banned string handling function 'fgetwc'. | +| test.cpp:216:3:216:13 | call to fputwc | Call to banned string handling function 'fputwc'. | +| test.cpp:217:3:217:13 | call to wcstol | Call to banned string handling function 'wcstol'. | +| test.cpp:218:3:218:14 | call to wcstoll | Call to banned string handling function 'wcstoll'. | +| test.cpp:219:3:219:14 | call to wcstoul | Call to banned string handling function 'wcstoul'. | +| test.cpp:220:3:220:15 | call to wcstoull | Call to banned string handling function 'wcstoull'. | +| test.cpp:221:3:221:13 | call to wcstod | Call to banned string handling function 'wcstod'. | +| test.cpp:222:3:222:13 | call to wcstof | Call to banned string handling function 'wcstof'. | +| test.cpp:223:3:223:14 | call to wcstold | Call to banned string handling function 'wcstold'. | +| test.cpp:232:3:232:16 | call to strtoumax | Call to banned string handling function 'strtoumax'. | +| test.cpp:233:3:233:16 | call to strtoimax | Call to banned string handling function 'strtoimax'. | +| test.cpp:234:3:234:16 | call to wcstoumax | Call to banned string handling function 'wcstoumax'. | +| test.cpp:235:3:235:16 | call to wcstoimax | Call to banned string handling function 'wcstoimax'. | +| test.cpp:239:40:239:50 | strcat | Address taken for banned string handling function 'strcat'. | +| test.cpp:240:39:240:49 | strcat | Address taken for banned string handling function 'strcat'. | +| test.cpp:241:42:241:53 | strchr | Address taken for banned string handling function 'strchr'. | +| test.cpp:242:42:242:52 | strchr | Address taken for banned string handling function 'strchr'. | +| test.cpp:243:44:243:54 | strcmp | Address taken for banned string handling function 'strcmp'. | +| test.cpp:244:43:244:53 | strcmp | Address taken for banned string handling function 'strcmp'. | +| test.cpp:245:44:245:55 | strcoll | Address taken for banned string handling function 'strcoll'. | +| test.cpp:246:43:246:54 | strcoll | Address taken for banned string handling function 'strcoll'. | +| test.cpp:247:40:247:50 | strcpy | Address taken for banned string handling function 'strcpy'. | +| test.cpp:248:40:248:50 | strcpy | Address taken for banned string handling function 'strcpy'. | +| test.cpp:249:48:249:59 | strcspn | Address taken for banned string handling function 'strcspn'. | +| test.cpp:250:47:250:58 | strcspn | Address taken for banned string handling function 'strcspn'. | +| test.cpp:251:24:251:36 | strerror | Address taken for banned string handling function 'strerror'. | +| test.cpp:252:23:252:35 | strerror | Address taken for banned string handling function 'strerror'. | +| test.cpp:253:34:253:44 | strlen | Address taken for banned string handling function 'strlen'. | +| test.cpp:254:33:254:43 | strlen | Address taken for banned string handling function 'strlen'. | +| test.cpp:255:49:255:60 | strncat | Address taken for banned string handling function 'strncat'. | +| test.cpp:256:48:256:59 | strncat | Address taken for banned string handling function 'strncat'. | +| test.cpp:258:8:258:19 | strncmp | Address taken for banned string handling function 'strncmp'. | +| test.cpp:260:7:260:18 | strncmp | Address taken for banned string handling function 'strncmp'. | +| test.cpp:261:49:261:60 | strncpy | Address taken for banned string handling function 'strncpy'. | +| test.cpp:262:48:262:59 | strncpy | Address taken for banned string handling function 'strncpy'. | +| test.cpp:264:7:264:19 | strpbrk | Address taken for banned string handling function 'strpbrk'. | +| test.cpp:266:7:266:18 | strpbrk | Address taken for banned string handling function 'strpbrk'. | +| test.cpp:267:43:267:55 | strrchr | Address taken for banned string handling function 'strrchr'. | +| test.cpp:268:43:268:54 | strrchr | Address taken for banned string handling function 'strrchr'. | +| test.cpp:269:48:269:58 | strspn | Address taken for banned string handling function 'strspn'. | +| test.cpp:270:47:270:57 | strspn | Address taken for banned string handling function 'strspn'. | +| test.cpp:272:7:272:18 | strstr | Address taken for banned string handling function 'strstr'. | +| test.cpp:273:52:273:62 | strstr | Address taken for banned string handling function 'strstr'. | +| test.cpp:274:41:274:51 | strtok | Address taken for banned string handling function 'strtok'. | +| test.cpp:275:40:275:50 | strtok | Address taken for banned string handling function 'strtok'. | +| test.cpp:276:50:276:61 | strxfrm | Address taken for banned string handling function 'strxfrm'. | +| test.cpp:277:49:277:60 | strxfrm | Address taken for banned string handling function 'strxfrm'. | +| test.cpp:281:45:281:55 | strtol | Address taken for banned string handling function 'strtol'. | +| test.cpp:282:44:282:54 | strtol | Address taken for banned string handling function 'strtol'. | +| test.cpp:283:50:283:61 | strtoll | Address taken for banned string handling function 'strtoll'. | +| test.cpp:284:49:284:60 | strtoll | Address taken for banned string handling function 'strtoll'. | +| test.cpp:286:8:286:19 | strtoul | Address taken for banned string handling function 'strtoul'. | +| test.cpp:288:7:288:18 | strtoul | Address taken for banned string handling function 'strtoul'. | +| test.cpp:290:8:290:20 | strtoull | Address taken for banned string handling function 'strtoull'. | +| test.cpp:292:7:292:19 | strtoull | Address taken for banned string handling function 'strtoull'. | +| test.cpp:293:42:293:52 | strtod | Address taken for banned string handling function 'strtod'. | +| test.cpp:294:42:294:52 | strtod | Address taken for banned string handling function 'strtod'. | +| test.cpp:295:42:295:52 | strtof | Address taken for banned string handling function 'strtof'. | +| test.cpp:296:41:296:51 | strtof | Address taken for banned string handling function 'strtof'. | +| test.cpp:297:48:297:59 | strtold | Address taken for banned string handling function 'strtold'. | +| test.cpp:298:47:298:58 | strtold | Address taken for banned string handling function 'strtold'. | +| test.cpp:302:27:302:37 | fgetwc | Address taken for banned string handling function 'fgetwc'. | +| test.cpp:303:26:303:36 | fgetwc | Address taken for banned string handling function 'fgetwc'. | +| test.cpp:304:36:304:46 | fputwc | Address taken for banned string handling function 'fputwc'. | +| test.cpp:305:35:305:45 | fputwc | Address taken for banned string handling function 'fputwc'. | +| test.cpp:306:51:306:61 | wcstol | Address taken for banned string handling function 'wcstol'. | +| test.cpp:307:50:307:60 | wcstol | Address taken for banned string handling function 'wcstol'. | +| test.cpp:309:8:309:19 | wcstoll | Address taken for banned string handling function 'wcstoll'. | +| test.cpp:311:7:311:18 | wcstoll | Address taken for banned string handling function 'wcstoll'. | +| test.cpp:313:8:313:19 | wcstoul | Address taken for banned string handling function 'wcstoul'. | +| test.cpp:315:7:315:18 | wcstoul | Address taken for banned string handling function 'wcstoul'. | +| test.cpp:317:8:317:20 | wcstoull | Address taken for banned string handling function 'wcstoull'. | +| test.cpp:319:7:319:19 | wcstoull | Address taken for banned string handling function 'wcstoull'. | +| test.cpp:320:49:320:59 | wcstod | Address taken for banned string handling function 'wcstod'. | +| test.cpp:321:48:321:58 | wcstod | Address taken for banned string handling function 'wcstod'. | +| test.cpp:322:48:322:58 | wcstof | Address taken for banned string handling function 'wcstof'. | +| test.cpp:323:47:323:57 | wcstof | Address taken for banned string handling function 'wcstof'. | +| test.cpp:325:8:325:19 | wcstold | Address taken for banned string handling function 'wcstold'. | +| test.cpp:327:7:327:18 | wcstold | Address taken for banned string handling function 'wcstold'. | +| test.cpp:332:8:332:21 | strtoumax | Address taken for banned string handling function 'strtoumax'. | +| test.cpp:333:49:333:62 | strtoumax | Address taken for banned string handling function 'strtoumax'. | +| test.cpp:334:49:334:62 | strtoimax | Address taken for banned string handling function 'strtoimax'. | +| test.cpp:335:48:335:61 | strtoimax | Address taken for banned string handling function 'strtoimax'. | +| test.cpp:337:8:337:21 | wcstoumax | Address taken for banned string handling function 'wcstoumax'. | +| test.cpp:339:7:339:20 | wcstoumax | Address taken for banned string handling function 'wcstoumax'. | +| test.cpp:341:8:341:21 | wcstoimax | Address taken for banned string handling function 'wcstoimax'. | +| test.cpp:343:7:343:20 | wcstoimax | Address taken for banned string handling function 'wcstoimax'. | diff --git a/cpp/misra/test/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.qlref b/cpp/misra/test/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.qlref new file mode 100644 index 0000000000..1b69df818c --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-2-2/UnsafeStringHandlingFunctions.qlref @@ -0,0 +1 @@ +rules/RULE-21-2-2/UnsafeStringHandlingFunctions.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-2-2/test.cpp b/cpp/misra/test/rules/RULE-21-2-2/test.cpp new file mode 100644 index 0000000000..a61639e6a5 --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-2-2/test.cpp @@ -0,0 +1,367 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void test_cstring_functions() { + char l1[100]; + char l2[100]; + const char *l3 = "test"; + + strcat(l1, l2); // NON_COMPLIANT + strchr(l3, 'e'); // NON_COMPLIANT + strcmp(l1, l2); // NON_COMPLIANT + strcoll(l1, l2); // NON_COMPLIANT + strcpy(l1, l3); // NON_COMPLIANT + strcspn(l1, l2); // NON_COMPLIANT + strerror(0); // NON_COMPLIANT + strlen(l3); // NON_COMPLIANT + strncat(l1, l2, 10); // NON_COMPLIANT + strncmp(l1, l2, 10); // NON_COMPLIANT + strncpy(l1, l3, 10); // NON_COMPLIANT + strpbrk(l1, l2); // NON_COMPLIANT + strrchr(l3, 'e'); // NON_COMPLIANT + strspn(l1, l2); // NON_COMPLIANT + strstr(l1, l3); // NON_COMPLIANT + strtok(l1, l2); // NON_COMPLIANT + strxfrm(l1, l2, 50); // NON_COMPLIANT +} + +void test_cstdlib_string_functions() { + const char *l1 = "123"; + char *l2; + + strtol(l1, &l2, 10); // NON_COMPLIANT + strtoll(l1, &l2, 10); // NON_COMPLIANT + strtoul(l1, &l2, 10); // NON_COMPLIANT + strtoull(l1, &l2, 10); // NON_COMPLIANT + strtod(l1, &l2); // NON_COMPLIANT + strtof(l1, &l2); // NON_COMPLIANT + strtold(l1, &l2); // NON_COMPLIANT +} + +void test_cwchar_functions() { + wchar_t l1[100]; + const wchar_t *l2 = L"123"; + wchar_t *l3; + FILE *l4 = nullptr; + + fgetwc(l4); // NON_COMPLIANT + fputwc(L'a', l4); // NON_COMPLIANT + wcstol(l2, &l3, 10); // NON_COMPLIANT + wcstoll(l2, &l3, 10); // NON_COMPLIANT + wcstoul(l2, &l3, 10); // NON_COMPLIANT + wcstoull(l2, &l3, 10); // NON_COMPLIANT + wcstod(l2, &l3); // NON_COMPLIANT + wcstof(l2, &l3); // NON_COMPLIANT + wcstold(l2, &l3); // NON_COMPLIANT +} + +void test_cinttypes_functions() { + const char *l1 = "123"; + char *l2; + const wchar_t *l3 = L"123"; + wchar_t *l4; + + strtoumax(l1, &l2, 10); // NON_COMPLIANT + strtoimax(l1, &l2, 10); // NON_COMPLIANT + wcstoumax(l3, &l4, 10); // NON_COMPLIANT + wcstoimax(l3, &l4, 10); // NON_COMPLIANT +} + +void test_cstring_function_pointer_addresses() { + char *(*l1)(char *, const char *) = &strcat; // NON_COMPLIANT + char *(*l2)(char *, const char *) = strcat; // NON_COMPLIANT + const char *(*l3)(const char *, int) = &strchr; // NON_COMPLIANT + const char *(*l4)(const char *, int) = strchr; // NON_COMPLIANT + int (*l5)(const char *, const char *) = &strcmp; // NON_COMPLIANT + int (*l6)(const char *, const char *) = strcmp; // NON_COMPLIANT + int (*l7)(const char *, const char *) = &strcoll; // NON_COMPLIANT + int (*l8)(const char *, const char *) = strcoll; // NON_COMPLIANT + char *(*l9)(char *, const char *) = &strcpy; // NON_COMPLIANT + char *(*l10)(char *, const char *) = strcpy; // NON_COMPLIANT + size_t (*l11)(const char *, const char *) = &strcspn; // NON_COMPLIANT + size_t (*l12)(const char *, const char *) = strcspn; // NON_COMPLIANT + char *(*l13)(int) = &strerror; // NON_COMPLIANT + char *(*l14)(int) = strerror; // NON_COMPLIANT + size_t (*l15)(const char *) = &strlen; // NON_COMPLIANT + size_t (*l16)(const char *) = strlen; // NON_COMPLIANT + char *(*l17)(char *, const char *, size_t) = &strncat; // NON_COMPLIANT + char *(*l18)(char *, const char *, size_t) = strncat; // NON_COMPLIANT + int (*l19)(const char *, const char *, size_t) = &strncmp; // NON_COMPLIANT + int (*l20)(const char *, const char *, size_t) = strncmp; // NON_COMPLIANT + char *(*l21)(char *, const char *, size_t) = &strncpy; // NON_COMPLIANT + char *(*l22)(char *, const char *, size_t) = strncpy; // NON_COMPLIANT + const char *(*l23)(const char *, const char *) = &strpbrk; // NON_COMPLIANT + const char *(*l24)(const char *, const char *) = strpbrk; // NON_COMPLIANT + const char *(*l25)(const char *, int) = &strrchr; // NON_COMPLIANT + const char *(*l26)(const char *, int) = strrchr; // NON_COMPLIANT + size_t (*l27)(const char *, const char *) = &strspn; // NON_COMPLIANT + size_t (*l28)(const char *, const char *) = strspn; // NON_COMPLIANT + const char *(*l29)(const char *, const char *) = &strstr; // NON_COMPLIANT + const char *(*l30)(const char *, const char *) = strstr; // NON_COMPLIANT + char *(*l31)(char *, const char *) = &strtok; // NON_COMPLIANT + char *(*l32)(char *, const char *) = strtok; // NON_COMPLIANT + size_t (*l33)(char *, const char *, size_t) = &strxfrm; // NON_COMPLIANT + size_t (*l34)(char *, const char *, size_t) = strxfrm; // NON_COMPLIANT +} + +void test_cstdlib_function_pointer_addresses() { + long (*l1)(const char *, char **, int) = &strtol; // NON_COMPLIANT + long (*l2)(const char *, char **, int) = strtol; // NON_COMPLIANT + long long (*l3)(const char *, char **, int) = &strtoll; // NON_COMPLIANT + long long (*l4)(const char *, char **, int) = strtoll; // NON_COMPLIANT + unsigned long (*l5)(const char *, char **, int) = &strtoul; // NON_COMPLIANT + unsigned long (*l6)(const char *, char **, int) = strtoul; // NON_COMPLIANT + unsigned long long (*l7)(const char *, char **, int) = + &strtoull; // NON_COMPLIANT + unsigned long long (*l8)(const char *, char **, int) = + strtoull; // NON_COMPLIANT + double (*l9)(const char *, char **) = &strtod; // NON_COMPLIANT + double (*l10)(const char *, char **) = strtod; // NON_COMPLIANT + float (*l11)(const char *, char **) = &strtof; // NON_COMPLIANT + float (*l12)(const char *, char **) = strtof; // NON_COMPLIANT + long double (*l13)(const char *, char **) = &strtold; // NON_COMPLIANT + long double (*l14)(const char *, char **) = strtold; // NON_COMPLIANT +} + +void test_cwchar_function_pointer_addresses() { + wint_t (*l1)(FILE *) = &fgetwc; // NON_COMPLIANT + wint_t (*l2)(FILE *) = fgetwc; // NON_COMPLIANT + wint_t (*l3)(wchar_t, FILE *) = &fputwc; // NON_COMPLIANT + wint_t (*l4)(wchar_t, FILE *) = fputwc; // NON_COMPLIANT + long (*l5)(const wchar_t *, wchar_t **, int) = &wcstol; // NON_COMPLIANT + long (*l6)(const wchar_t *, wchar_t **, int) = wcstol; // NON_COMPLIANT + long long (*l7)(const wchar_t *, wchar_t **, int) = &wcstoll; // NON_COMPLIANT + long long (*l8)(const wchar_t *, wchar_t **, int) = wcstoll; // NON_COMPLIANT + unsigned long (*l9)(const wchar_t *, wchar_t **, int) = + &wcstoul; // NON_COMPLIANT + unsigned long (*l10)(const wchar_t *, wchar_t **, int) = + wcstoul; // NON_COMPLIANT + unsigned long long (*l11)(const wchar_t *, wchar_t **, int) = + &wcstoull; // NON_COMPLIANT + unsigned long long (*l12)(const wchar_t *, wchar_t **, int) = + wcstoull; // NON_COMPLIANT + double (*l13)(const wchar_t *, wchar_t **) = &wcstod; // NON_COMPLIANT + double (*l14)(const wchar_t *, wchar_t **) = wcstod; // NON_COMPLIANT + float (*l15)(const wchar_t *, wchar_t **) = &wcstof; // NON_COMPLIANT + float (*l16)(const wchar_t *, wchar_t **) = wcstof; // NON_COMPLIANT + long double (*l17)(const wchar_t *, wchar_t **) = &wcstold; // NON_COMPLIANT + long double (*l18)(const wchar_t *, wchar_t **) = wcstold; // NON_COMPLIANT +} + +void test_cinttypes_function_pointer_addresses() { + uintmax_t (*l1)(const char *, char **, int) = &strtoumax; // NON_COMPLIANT + uintmax_t (*l2)(const char *, char **, int) = strtoumax; // NON_COMPLIANT + intmax_t (*l3)(const char *, char **, int) = &strtoimax; // NON_COMPLIANT + intmax_t (*l4)(const char *, char **, int) = strtoimax; // NON_COMPLIANT + uintmax_t (*l5)(const wchar_t *, wchar_t **, int) = + &wcstoumax; // NON_COMPLIANT + uintmax_t (*l6)(const wchar_t *, wchar_t **, int) = + wcstoumax; // NON_COMPLIANT + intmax_t (*l7)(const wchar_t *, wchar_t **, int) = + &wcstoimax; // NON_COMPLIANT + intmax_t (*l8)(const wchar_t *, wchar_t **, int) = wcstoimax; // NON_COMPLIANT +} + +void test_std_cstring_functions() { + char l1[100]; + char l2[100]; + const char *l3 = "test"; + + std::strcat(l1, l2); // NON_COMPLIANT + std::strchr(l3, 'e'); // NON_COMPLIANT + std::strcmp(l1, l2); // NON_COMPLIANT + std::strcoll(l1, l2); // NON_COMPLIANT + std::strcpy(l1, l3); // NON_COMPLIANT + std::strcspn(l1, l2); // NON_COMPLIANT + std::strerror(0); // NON_COMPLIANT + std::strlen(l3); // NON_COMPLIANT + std::strncat(l1, l2, 10); // NON_COMPLIANT + std::strncmp(l1, l2, 10); // NON_COMPLIANT + std::strncpy(l1, l3, 10); // NON_COMPLIANT + std::strpbrk(l1, l2); // NON_COMPLIANT + std::strrchr(l3, 'e'); // NON_COMPLIANT + std::strspn(l1, l2); // NON_COMPLIANT + std::strstr(l1, l3); // NON_COMPLIANT + std::strtok(l1, l2); // NON_COMPLIANT + std::strxfrm(l1, l2, 50); // NON_COMPLIANT +} + +void test_std_cstdlib_string_functions() { + const char *l1 = "123"; + char *l2; + + std::strtol(l1, &l2, 10); // NON_COMPLIANT + std::strtoll(l1, &l2, 10); // NON_COMPLIANT + std::strtoul(l1, &l2, 10); // NON_COMPLIANT + std::strtoull(l1, &l2, 10); // NON_COMPLIANT + std::strtod(l1, &l2); // NON_COMPLIANT + std::strtof(l1, &l2); // NON_COMPLIANT + std::strtold(l1, &l2); // NON_COMPLIANT +} + +void test_std_cwchar_functions() { + wchar_t l1[100]; + const wchar_t *l2 = L"123"; + wchar_t *l3; + FILE *l4 = nullptr; + + std::fgetwc(l4); // NON_COMPLIANT + std::fputwc(L'a', l4); // NON_COMPLIANT + std::wcstol(l2, &l3, 10); // NON_COMPLIANT + std::wcstoll(l2, &l3, 10); // NON_COMPLIANT + std::wcstoul(l2, &l3, 10); // NON_COMPLIANT + std::wcstoull(l2, &l3, 10); // NON_COMPLIANT + std::wcstod(l2, &l3); // NON_COMPLIANT + std::wcstof(l2, &l3); // NON_COMPLIANT + std::wcstold(l2, &l3); // NON_COMPLIANT +} + +void test_std_cinttypes_functions() { + const char *l1 = "123"; + char *l2; + const wchar_t *l3 = L"123"; + wchar_t *l4; + + std::strtoumax(l1, &l2, 10); // NON_COMPLIANT + std::strtoimax(l1, &l2, 10); // NON_COMPLIANT + std::wcstoumax(l3, &l4, 10); // NON_COMPLIANT + std::wcstoimax(l3, &l4, 10); // NON_COMPLIANT +} + +void test_std_cstring_function_pointer_addresses() { + char *(*l1)(char *, const char *) = &std::strcat; // NON_COMPLIANT + char *(*l2)(char *, const char *) = std::strcat; // NON_COMPLIANT + const char *(*l3)(const char *, int) = &std::strchr; // NON_COMPLIANT + const char *(*l4)(const char *, int) = std::strchr; // NON_COMPLIANT + int (*l5)(const char *, const char *) = &std::strcmp; // NON_COMPLIANT + int (*l6)(const char *, const char *) = std::strcmp; // NON_COMPLIANT + int (*l7)(const char *, const char *) = &std::strcoll; // NON_COMPLIANT + int (*l8)(const char *, const char *) = std::strcoll; // NON_COMPLIANT + char *(*l9)(char *, const char *) = &std::strcpy; // NON_COMPLIANT + char *(*l10)(char *, const char *) = std::strcpy; // NON_COMPLIANT + size_t (*l11)(const char *, const char *) = &std::strcspn; // NON_COMPLIANT + size_t (*l12)(const char *, const char *) = std::strcspn; // NON_COMPLIANT + char *(*l13)(int) = &std::strerror; // NON_COMPLIANT + char *(*l14)(int) = std::strerror; // NON_COMPLIANT + size_t (*l15)(const char *) = &std::strlen; // NON_COMPLIANT + size_t (*l16)(const char *) = std::strlen; // NON_COMPLIANT + char *(*l17)(char *, const char *, size_t) = &std::strncat; // NON_COMPLIANT + char *(*l18)(char *, const char *, size_t) = std::strncat; // NON_COMPLIANT + int (*l19)(const char *, const char *, size_t) = + &std::strncmp; // NON_COMPLIANT + int (*l20)(const char *, const char *, size_t) = + std::strncmp; // NON_COMPLIANT + char *(*l21)(char *, const char *, size_t) = &std::strncpy; // NON_COMPLIANT + char *(*l22)(char *, const char *, size_t) = std::strncpy; // NON_COMPLIANT + const char *(*l23)(const char *, const char *) = + &std::strpbrk; // NON_COMPLIANT + const char *(*l24)(const char *, const char *) = + std::strpbrk; // NON_COMPLIANT + const char *(*l25)(const char *, int) = &std::strrchr; // NON_COMPLIANT + const char *(*l26)(const char *, int) = std::strrchr; // NON_COMPLIANT + size_t (*l27)(const char *, const char *) = &std::strspn; // NON_COMPLIANT + size_t (*l28)(const char *, const char *) = std::strspn; // NON_COMPLIANT + const char *(*l29)(const char *, const char *) = + &std::strstr; // NON_COMPLIANT + const char *(*l30)(const char *, const char *) = std::strstr; // NON_COMPLIANT + char *(*l31)(char *, const char *) = &std::strtok; // NON_COMPLIANT + char *(*l32)(char *, const char *) = std::strtok; // NON_COMPLIANT + size_t (*l33)(char *, const char *, size_t) = &std::strxfrm; // NON_COMPLIANT + size_t (*l34)(char *, const char *, size_t) = std::strxfrm; // NON_COMPLIANT +} + +void test_std_cstdlib_function_pointer_addresses() { + long (*l1)(const char *, char **, int) = &std::strtol; // NON_COMPLIANT + long (*l2)(const char *, char **, int) = std::strtol; // NON_COMPLIANT + long long (*l3)(const char *, char **, int) = &std::strtoll; // NON_COMPLIANT + long long (*l4)(const char *, char **, int) = std::strtoll; // NON_COMPLIANT + unsigned long (*l5)(const char *, char **, int) = + &std::strtoul; // NON_COMPLIANT + unsigned long (*l6)(const char *, char **, int) = + std::strtoul; // NON_COMPLIANT + unsigned long long (*l7)(const char *, char **, int) = + &std::strtoull; // NON_COMPLIANT + unsigned long long (*l8)(const char *, char **, int) = + std::strtoull; // NON_COMPLIANT + double (*l9)(const char *, char **) = &std::strtod; // NON_COMPLIANT + double (*l10)(const char *, char **) = std::strtod; // NON_COMPLIANT + float (*l11)(const char *, char **) = &std::strtof; // NON_COMPLIANT + float (*l12)(const char *, char **) = std::strtof; // NON_COMPLIANT + long double (*l13)(const char *, char **) = &std::strtold; // NON_COMPLIANT + long double (*l14)(const char *, char **) = std::strtold; // NON_COMPLIANT +} + +void test_std_cwchar_function_pointer_addresses() { + wint_t (*l1)(FILE *) = &std::fgetwc; // NON_COMPLIANT + wint_t (*l2)(FILE *) = std::fgetwc; // NON_COMPLIANT + wint_t (*l3)(wchar_t, FILE *) = &std::fputwc; // NON_COMPLIANT + wint_t (*l4)(wchar_t, FILE *) = std::fputwc; // NON_COMPLIANT + long (*l5)(const wchar_t *, wchar_t **, int) = &std::wcstol; // NON_COMPLIANT + long (*l6)(const wchar_t *, wchar_t **, int) = std::wcstol; // NON_COMPLIANT + long long (*l7)(const wchar_t *, wchar_t **, int) = + &std::wcstoll; // NON_COMPLIANT + long long (*l8)(const wchar_t *, wchar_t **, int) = + std::wcstoll; // NON_COMPLIANT + unsigned long (*l9)(const wchar_t *, wchar_t **, int) = + &std::wcstoul; // NON_COMPLIANT + unsigned long (*l10)(const wchar_t *, wchar_t **, int) = + std::wcstoul; // NON_COMPLIANT + unsigned long long (*l11)(const wchar_t *, wchar_t **, int) = + &std::wcstoull; // NON_COMPLIANT + unsigned long long (*l12)(const wchar_t *, wchar_t **, int) = + std::wcstoull; // NON_COMPLIANT + double (*l13)(const wchar_t *, wchar_t **) = &std::wcstod; // NON_COMPLIANT + double (*l14)(const wchar_t *, wchar_t **) = std::wcstod; // NON_COMPLIANT + float (*l15)(const wchar_t *, wchar_t **) = &std::wcstof; // NON_COMPLIANT + float (*l16)(const wchar_t *, wchar_t **) = std::wcstof; // NON_COMPLIANT + long double (*l17)(const wchar_t *, wchar_t **) = + &std::wcstold; // NON_COMPLIANT + long double (*l18)(const wchar_t *, wchar_t **) = + std::wcstold; // NON_COMPLIANT +} + +void test_std_cinttypes_function_pointer_addresses() { + uintmax_t (*l1)(const char *, char **, int) = + &std::strtoumax; // NON_COMPLIANT + uintmax_t (*l2)(const char *, char **, int) = std::strtoumax; // NON_COMPLIANT + intmax_t (*l3)(const char *, char **, int) = &std::strtoimax; // NON_COMPLIANT + intmax_t (*l4)(const char *, char **, int) = std::strtoimax; // NON_COMPLIANT + uintmax_t (*l5)(const wchar_t *, wchar_t **, int) = + &std::wcstoumax; // NON_COMPLIANT + uintmax_t (*l6)(const wchar_t *, wchar_t **, int) = + std::wcstoumax; // NON_COMPLIANT + intmax_t (*l7)(const wchar_t *, wchar_t **, int) = + &std::wcstoimax; // NON_COMPLIANT + intmax_t (*l8)(const wchar_t *, wchar_t **, int) = + std::wcstoimax; // NON_COMPLIANT +} + +void test_compliant_alternatives() { + char l1[100]; + const char *l2 = "test"; + std::size_t l3 = 50; + + // Using std::string_view instead of strlen + std::string_view l4 = l2; + if (l4.size() + 1u < l3) { // COMPLIANT + l4.copy(l1, l4.size()); // COMPLIANT + l1[l4.size()] = 0; // COMPLIANT + } + + // Using std::string for string operations + std::string l5 = "hello"; + std::string l6 = "world"; + std::string l7 = l5 + l6; // COMPLIANT + + // Using standard library numeric conversions + std::string l8 = "123"; + std::int32_t l9 = std::stoi(l8); // COMPLIANT + double l10 = std::stod(l8); // COMPLIANT +} \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-2-3/BannedSystemFunction.expected b/cpp/misra/test/rules/RULE-21-2-3/BannedSystemFunction.expected new file mode 100644 index 0000000000..fcb5a8aeee --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-2-3/BannedSystemFunction.expected @@ -0,0 +1,9 @@ +| test.cpp:4:3:4:13 | call to system | Call to banned function 'system'. | +| test.cpp:8:14:8:24 | system | Address taken for banned function 'system'. | +| test.cpp:9:29:9:39 | system | Address taken for banned function 'system'. | +| test.cpp:13:40:13:50 | system | Address taken for banned function 'system'. | +| test.cpp:17:3:17:13 | call to system | Call to banned function 'system'. | +| test.cpp:22:3:22:13 | call to system | Call to banned function 'system'. | +| test.cpp:35:3:35:8 | call to system | Call to banned function 'system'. | +| test.cpp:39:29:39:34 | system | Address taken for banned function 'system'. | +| test.cpp:44:3:44:21 | system(x) | Use of banned macro 'system'. | diff --git a/cpp/misra/test/rules/RULE-21-2-3/BannedSystemFunction.qlref b/cpp/misra/test/rules/RULE-21-2-3/BannedSystemFunction.qlref new file mode 100644 index 0000000000..2580c7a6a9 --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-2-3/BannedSystemFunction.qlref @@ -0,0 +1 @@ +rules/RULE-21-2-3/BannedSystemFunction.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-2-3/test.cpp b/cpp/misra/test/rules/RULE-21-2-3/test.cpp new file mode 100644 index 0000000000..89ed82d88f --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-2-3/test.cpp @@ -0,0 +1,45 @@ +#include + +void test_direct_call_to_system() { + std::system("echo hello"); // NON_COMPLIANT +} + +void test_system_function_pointer() { + auto l1 = &std::system; // NON_COMPLIANT + int (*l2)(const char *) = std::system; // NON_COMPLIANT +} + +void test_system_address_taken() { + void *l1 = reinterpret_cast(&std::system); // NON_COMPLIANT +} + +void test_system_call_with_null() { + std::system(nullptr); // NON_COMPLIANT +} + +void test_system_call_with_variable() { + const char *l1 = "ls"; + std::system(l1); // NON_COMPLIANT +} + +void test_compliant_alternative() { + // Using compliant alternatives instead of system() + const char *l1 = "some command"; // COMPLIANT + // Implementation-specific alternatives would be used here +} + +// Test with C-style header (rule also applies to ) +#include + +void test_c_style_header_system() { + system("echo hello"); // NON_COMPLIANT +} + +void test_c_style_header_function_pointer() { + int (*l1)(const char *) = system; // NON_COMPLIANT +} + +#define system(x) 0 +void test_system_macro_expansion() { + system("echo test"); // NON_COMPLIANT +} diff --git a/cpp/misra/test/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.expected b/cpp/misra/test/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.expected new file mode 100644 index 0000000000..a6d399c0d2 --- /dev/null +++ b/cpp/misra/test/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.expected @@ -0,0 +1,9 @@ +| test.cpp:23:25:23:27 | call to shared_ptr | Use of raw pointer constructor for 'std::shared_ptr'. | +| test.cpp:28:25:28:27 | call to unique_ptr | Use of raw pointer constructor for 'std::unique_ptr'. | +| test.cpp:34:3:34:32 | call to shared_ptr | Use of raw pointer constructor for 'std::shared_ptr'. | +| test.cpp:40:3:40:32 | call to unique_ptr | Use of raw pointer constructor for 'std::unique_ptr'. | +| test.cpp:46:6:46:32 | call to shared_ptr | Use of raw pointer constructor for 'std::shared_ptr'. | +| test.cpp:47:6:47:32 | call to shared_ptr | Use of raw pointer constructor for 'std::shared_ptr'. | +| test.cpp:57:27:57:29 | call to unique_ptr | Use of raw pointer constructor for 'std::unique_ptr'. | +| test.cpp:67:25:67:31 | call to shared_ptr | Use of raw pointer constructor for 'std::shared_ptr'. | +| test.cpp:74:39:74:45 | call to unique_ptr | Use of raw pointer constructor for 'std::unique_ptr'. | diff --git a/cpp/misra/test/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.qlref b/cpp/misra/test/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.qlref new file mode 100644 index 0000000000..337d1b2ade --- /dev/null +++ b/cpp/misra/test/rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.qlref @@ -0,0 +1 @@ +rules/RULE-23-11-1/UseSmartPtrFactoryFunctions.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-23-11-1/test.cpp b/cpp/misra/test/rules/RULE-23-11-1/test.cpp new file mode 100644 index 0000000000..1f0cb2cf7a --- /dev/null +++ b/cpp/misra/test/rules/RULE-23-11-1/test.cpp @@ -0,0 +1,84 @@ +#include +#include + +struct A { + std::int8_t i; +}; + +class B {}; + +void test_make_shared_compliant() { + auto p = std::make_shared(); // COMPLIANT + std::int8_t *pi = &(p->i); + std::shared_ptr q( + p, pi); // COMPLIANT - aliasing constructor, not taking ownership +} + +void test_make_unique_compliant() { + auto p = std::make_unique(); // COMPLIANT +} + +void test_raw_pointer_shared_ptr_non_compliant() { + A *l1 = new A(); + std::shared_ptr l2(l1); // NON_COMPLIANT +} + +void test_raw_pointer_unique_ptr_non_compliant() { + A *l1 = new A(); + std::unique_ptr l2(l1); // NON_COMPLIANT +} + +auto test_exception_safety_issue() { + auto *l1 = new A(); + auto l2 = std::make_unique(); // may throw + return std::shared_ptr(l1); // NON_COMPLIANT - memory leak + // if make_unique throws +} + +auto test_double_delete_issue(std::unique_ptr p) { + auto l1 = p.get(); + return std::unique_ptr(l1); // NON_COMPLIANT - causes double delete +} + +void f1(std::shared_ptr a, std::shared_ptr b); + +void test_function_argument_non_compliant() { + f1(std::shared_ptr(new A()), // NON_COMPLIANT + std::shared_ptr(new B())); // NON_COMPLIANT +} + +void test_function_argument_compliant() { + f1(std::make_shared(), // COMPLIANT + std::make_shared()); // COMPLIANT +} + +void test_array_raw_pointer_non_compliant() { + A *l1 = new A[10]; + std::unique_ptr l2(l1); // NON_COMPLIANT +} + +void test_array_make_unique_compliant() { + auto l1 = std::make_unique(10); // COMPLIANT +} + +void test_custom_deleter_shared_ptr() { + A *l1 = new A(); + auto l2 = [](A *p) { delete p; }; + std::shared_ptr l3(l1, l2); // NON_COMPLIANT - still + // using raw pointer constructor +} + +void test_custom_deleter_unique_ptr() { + A *l1 = new A(); + auto l2 = [](A *p) { delete p; }; + std::unique_ptr l3(l1, l2); // NON_COMPLIANT - still + // using raw pointer constructor +} + +void test_nullptr_shared_ptr() { + std::shared_ptr l1(nullptr); // COMPLIANT - no ownership taken +} + +void test_nullptr_unique_ptr() { + std::unique_ptr l1(nullptr); // COMPLIANT - no ownership taken +} \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.expected b/cpp/misra/test/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.expected new file mode 100644 index 0000000000..1c02073fb9 --- /dev/null +++ b/cpp/misra/test/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.expected @@ -0,0 +1,132 @@ +| test.cpp:11:3:11:14 | call to isalnum | Call to banned character handling function 'isalnum' from or . | +| test.cpp:12:3:12:14 | call to isalpha | Call to banned character handling function 'isalpha' from or . | +| test.cpp:13:3:13:14 | call to isblank | Call to banned character handling function 'isblank' from or . | +| test.cpp:14:3:14:14 | call to iscntrl | Call to banned character handling function 'iscntrl' from or . | +| test.cpp:15:3:15:14 | call to isdigit | Call to banned character handling function 'isdigit' from or . | +| test.cpp:16:3:16:14 | call to isgraph | Call to banned character handling function 'isgraph' from or . | +| test.cpp:17:3:17:14 | call to islower | Call to banned character handling function 'islower' from or . | +| test.cpp:18:3:18:14 | call to isprint | Call to banned character handling function 'isprint' from or . | +| test.cpp:19:3:19:14 | call to ispunct | Call to banned character handling function 'ispunct' from or . | +| test.cpp:20:3:20:14 | call to isspace | Call to banned character handling function 'isspace' from or . | +| test.cpp:21:3:21:14 | call to isupper | Call to banned character handling function 'isupper' from or . | +| test.cpp:22:3:22:15 | call to isxdigit | Call to banned character handling function 'isxdigit' from or . | +| test.cpp:25:3:25:14 | call to tolower | Call to banned character handling function 'tolower' from or . | +| test.cpp:26:3:26:14 | call to toupper | Call to banned character handling function 'toupper' from or . | +| test.cpp:33:3:33:9 | call to isalnum | Call to banned character handling function 'isalnum' from or . | +| test.cpp:34:3:34:9 | call to isalpha | Call to banned character handling function 'isalpha' from or . | +| test.cpp:35:3:35:9 | call to isblank | Call to banned character handling function 'isblank' from or . | +| test.cpp:36:3:36:9 | call to iscntrl | Call to banned character handling function 'iscntrl' from or . | +| test.cpp:37:3:37:9 | call to isdigit | Call to banned character handling function 'isdigit' from or . | +| test.cpp:38:3:38:9 | call to isgraph | Call to banned character handling function 'isgraph' from or . | +| test.cpp:39:3:39:9 | call to islower | Call to banned character handling function 'islower' from or . | +| test.cpp:40:3:40:9 | call to isprint | Call to banned character handling function 'isprint' from or . | +| test.cpp:41:3:41:9 | call to ispunct | Call to banned character handling function 'ispunct' from or . | +| test.cpp:42:3:42:9 | call to isspace | Call to banned character handling function 'isspace' from or . | +| test.cpp:43:3:43:9 | call to isupper | Call to banned character handling function 'isupper' from or . | +| test.cpp:44:3:44:10 | call to isxdigit | Call to banned character handling function 'isxdigit' from or . | +| test.cpp:47:3:47:9 | call to tolower | Call to banned character handling function 'tolower' from or . | +| test.cpp:48:3:48:9 | call to toupper | Call to banned character handling function 'toupper' from or . | +| test.cpp:55:3:55:15 | call to iswalnum | Call to banned character handling function 'iswalnum' from or . | +| test.cpp:56:3:56:15 | call to iswalpha | Call to banned character handling function 'iswalpha' from or . | +| test.cpp:57:3:57:15 | call to iswblank | Call to banned character handling function 'iswblank' from or . | +| test.cpp:58:3:58:15 | call to iswcntrl | Call to banned character handling function 'iswcntrl' from or . | +| test.cpp:59:3:59:15 | call to iswdigit | Call to banned character handling function 'iswdigit' from or . | +| test.cpp:60:3:60:15 | call to iswgraph | Call to banned character handling function 'iswgraph' from or . | +| test.cpp:61:3:61:15 | call to iswlower | Call to banned character handling function 'iswlower' from or . | +| test.cpp:62:3:62:15 | call to iswprint | Call to banned character handling function 'iswprint' from or . | +| test.cpp:63:3:63:15 | call to iswpunct | Call to banned character handling function 'iswpunct' from or . | +| test.cpp:64:3:64:15 | call to iswspace | Call to banned character handling function 'iswspace' from or . | +| test.cpp:65:3:65:15 | call to iswupper | Call to banned character handling function 'iswupper' from or . | +| test.cpp:66:3:66:16 | call to iswxdigit | Call to banned character handling function 'iswxdigit' from or . | +| test.cpp:69:3:69:15 | call to towlower | Call to banned character handling function 'towlower' from or . | +| test.cpp:70:3:70:15 | call to towupper | Call to banned character handling function 'towupper' from or . | +| test.cpp:73:3:73:13 | call to wctype | Call to banned character handling function 'wctype' from or . | +| test.cpp:74:3:74:15 | call to iswctype | Call to banned character handling function 'iswctype' from or . | +| test.cpp:74:21:74:31 | call to wctype | Call to banned character handling function 'wctype' from or . | +| test.cpp:75:3:75:14 | call to wctrans | Call to banned character handling function 'wctrans' from or . | +| test.cpp:76:3:76:16 | call to towctrans | Call to banned character handling function 'towctrans' from or . | +| test.cpp:76:22:76:33 | call to wctrans | Call to banned character handling function 'wctrans' from or . | +| test.cpp:83:3:83:10 | call to iswalnum | Call to banned character handling function 'iswalnum' from or . | +| test.cpp:84:3:84:10 | call to iswalpha | Call to banned character handling function 'iswalpha' from or . | +| test.cpp:85:3:85:10 | call to iswblank | Call to banned character handling function 'iswblank' from or . | +| test.cpp:86:3:86:10 | call to iswcntrl | Call to banned character handling function 'iswcntrl' from or . | +| test.cpp:87:3:87:10 | call to iswdigit | Call to banned character handling function 'iswdigit' from or . | +| test.cpp:88:3:88:10 | call to iswgraph | Call to banned character handling function 'iswgraph' from or . | +| test.cpp:89:3:89:10 | call to iswlower | Call to banned character handling function 'iswlower' from or . | +| test.cpp:90:3:90:10 | call to iswprint | Call to banned character handling function 'iswprint' from or . | +| test.cpp:91:3:91:10 | call to iswpunct | Call to banned character handling function 'iswpunct' from or . | +| test.cpp:92:3:92:10 | call to iswspace | Call to banned character handling function 'iswspace' from or . | +| test.cpp:93:3:93:10 | call to iswupper | Call to banned character handling function 'iswupper' from or . | +| test.cpp:94:3:94:11 | call to iswxdigit | Call to banned character handling function 'iswxdigit' from or . | +| test.cpp:97:3:97:10 | call to towlower | Call to banned character handling function 'towlower' from or . | +| test.cpp:98:3:98:10 | call to towupper | Call to banned character handling function 'towupper' from or . | +| test.cpp:101:3:101:8 | call to wctype | Call to banned character handling function 'wctype' from or . | +| test.cpp:102:3:102:10 | call to iswctype | Call to banned character handling function 'iswctype' from or . | +| test.cpp:102:16:102:21 | call to wctype | Call to banned character handling function 'wctype' from or . | +| test.cpp:103:3:103:9 | call to wctrans | Call to banned character handling function 'wctrans' from or . | +| test.cpp:104:3:104:11 | call to towctrans | Call to banned character handling function 'towctrans' from or . | +| test.cpp:104:17:104:23 | call to wctrans | Call to banned character handling function 'wctrans' from or . | +| test.cpp:109:20:109:32 | isalnum | Address taken for banned character handling function 'isalnum' from or . | +| test.cpp:110:20:110:32 | isalpha | Address taken for banned character handling function 'isalpha' from or . | +| test.cpp:111:20:111:32 | isblank | Address taken for banned character handling function 'isblank' from or . | +| test.cpp:112:20:112:32 | iscntrl | Address taken for banned character handling function 'iscntrl' from or . | +| test.cpp:113:20:113:32 | isdigit | Address taken for banned character handling function 'isdigit' from or . | +| test.cpp:114:20:114:32 | isgraph | Address taken for banned character handling function 'isgraph' from or . | +| test.cpp:115:20:115:32 | islower | Address taken for banned character handling function 'islower' from or . | +| test.cpp:116:20:116:32 | isprint | Address taken for banned character handling function 'isprint' from or . | +| test.cpp:117:20:117:32 | ispunct | Address taken for banned character handling function 'ispunct' from or . | +| test.cpp:118:21:118:33 | isspace | Address taken for banned character handling function 'isspace' from or . | +| test.cpp:119:21:119:33 | isupper | Address taken for banned character handling function 'isupper' from or . | +| test.cpp:120:21:120:34 | isxdigit | Address taken for banned character handling function 'isxdigit' from or . | +| test.cpp:121:21:121:33 | tolower | Address taken for banned character handling function 'tolower' from or . | +| test.cpp:122:21:122:33 | toupper | Address taken for banned character handling function 'toupper' from or . | +| test.cpp:125:22:125:28 | isalnum | Address taken for banned character handling function 'isalnum' from or . | +| test.cpp:126:22:126:28 | isalpha | Address taken for banned character handling function 'isalpha' from or . | +| test.cpp:127:22:127:28 | isblank | Address taken for banned character handling function 'isblank' from or . | +| test.cpp:128:22:128:28 | iscntrl | Address taken for banned character handling function 'iscntrl' from or . | +| test.cpp:129:22:129:28 | isdigit | Address taken for banned character handling function 'isdigit' from or . | +| test.cpp:130:22:130:28 | isgraph | Address taken for banned character handling function 'isgraph' from or . | +| test.cpp:131:22:131:28 | islower | Address taken for banned character handling function 'islower' from or . | +| test.cpp:132:22:132:28 | isprint | Address taken for banned character handling function 'isprint' from or . | +| test.cpp:133:22:133:28 | ispunct | Address taken for banned character handling function 'ispunct' from or . | +| test.cpp:134:22:134:28 | isspace | Address taken for banned character handling function 'isspace' from or . | +| test.cpp:135:22:135:28 | isupper | Address taken for banned character handling function 'isupper' from or . | +| test.cpp:136:22:136:29 | isxdigit | Address taken for banned character handling function 'isxdigit' from or . | +| test.cpp:137:22:137:28 | tolower | Address taken for banned character handling function 'tolower' from or . | +| test.cpp:138:22:138:28 | toupper | Address taken for banned character handling function 'toupper' from or . | +| test.cpp:141:25:141:37 | iswalnum | Address taken for banned character handling function 'iswalnum' from or . | +| test.cpp:142:25:142:37 | iswalpha | Address taken for banned character handling function 'iswalpha' from or . | +| test.cpp:143:25:143:37 | iswblank | Address taken for banned character handling function 'iswblank' from or . | +| test.cpp:144:25:144:37 | iswcntrl | Address taken for banned character handling function 'iswcntrl' from or . | +| test.cpp:145:25:145:37 | iswdigit | Address taken for banned character handling function 'iswdigit' from or . | +| test.cpp:146:25:146:37 | iswgraph | Address taken for banned character handling function 'iswgraph' from or . | +| test.cpp:147:25:147:37 | iswlower | Address taken for banned character handling function 'iswlower' from or . | +| test.cpp:148:25:148:37 | iswprint | Address taken for banned character handling function 'iswprint' from or . | +| test.cpp:149:25:149:37 | iswpunct | Address taken for banned character handling function 'iswpunct' from or . | +| test.cpp:150:25:150:37 | iswspace | Address taken for banned character handling function 'iswspace' from or . | +| test.cpp:151:25:151:37 | iswupper | Address taken for banned character handling function 'iswupper' from or . | +| test.cpp:152:25:152:38 | iswxdigit | Address taken for banned character handling function 'iswxdigit' from or . | +| test.cpp:153:28:153:40 | towlower | Address taken for banned character handling function 'towlower' from or . | +| test.cpp:154:28:154:40 | towupper | Address taken for banned character handling function 'towupper' from or . | +| test.cpp:155:36:155:46 | wctype | Address taken for banned character handling function 'wctype' from or . | +| test.cpp:156:35:156:47 | iswctype | Address taken for banned character handling function 'iswctype' from or . | +| test.cpp:157:37:157:48 | wctrans | Address taken for banned character handling function 'wctrans' from or . | +| test.cpp:158:39:158:52 | towctrans | Address taken for banned character handling function 'towctrans' from or . | +| test.cpp:161:25:161:32 | iswalnum | Address taken for banned character handling function 'iswalnum' from or . | +| test.cpp:162:25:162:32 | iswalpha | Address taken for banned character handling function 'iswalpha' from or . | +| test.cpp:163:25:163:32 | iswblank | Address taken for banned character handling function 'iswblank' from or . | +| test.cpp:164:25:164:32 | iswcntrl | Address taken for banned character handling function 'iswcntrl' from or . | +| test.cpp:165:25:165:32 | iswdigit | Address taken for banned character handling function 'iswdigit' from or . | +| test.cpp:166:25:166:32 | iswgraph | Address taken for banned character handling function 'iswgraph' from or . | +| test.cpp:167:25:167:32 | iswlower | Address taken for banned character handling function 'iswlower' from or . | +| test.cpp:168:25:168:32 | iswprint | Address taken for banned character handling function 'iswprint' from or . | +| test.cpp:169:25:169:32 | iswpunct | Address taken for banned character handling function 'iswpunct' from or . | +| test.cpp:170:25:170:32 | iswspace | Address taken for banned character handling function 'iswspace' from or . | +| test.cpp:171:25:171:32 | iswupper | Address taken for banned character handling function 'iswupper' from or . | +| test.cpp:172:25:172:33 | iswxdigit | Address taken for banned character handling function 'iswxdigit' from or . | +| test.cpp:173:28:173:35 | towlower | Address taken for banned character handling function 'towlower' from or . | +| test.cpp:174:28:174:35 | towupper | Address taken for banned character handling function 'towupper' from or . | +| test.cpp:175:36:175:41 | wctype | Address taken for banned character handling function 'wctype' from or . | +| test.cpp:176:35:176:42 | iswctype | Address taken for banned character handling function 'iswctype' from or . | +| test.cpp:177:37:177:43 | wctrans | Address taken for banned character handling function 'wctrans' from or . | +| test.cpp:178:39:178:47 | towctrans | Address taken for banned character handling function 'towctrans' from or . | diff --git a/cpp/misra/test/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.qlref b/cpp/misra/test/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.qlref new file mode 100644 index 0000000000..a2ac2abeab --- /dev/null +++ b/cpp/misra/test/rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.qlref @@ -0,0 +1 @@ +rules/RULE-24-5-1/CharacterHandlingFunctionRestrictions.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-24-5-1/test.cpp b/cpp/misra/test/rules/RULE-24-5-1/test.cpp new file mode 100644 index 0000000000..6c06441c8d --- /dev/null +++ b/cpp/misra/test/rules/RULE-24-5-1/test.cpp @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include + +void test_cctype_functions() { + char l1 = 'A'; + + // Character classification functions from + std::isalnum(l1); // NON_COMPLIANT + std::isalpha(l1); // NON_COMPLIANT + std::isblank(l1); // NON_COMPLIANT + std::iscntrl(l1); // NON_COMPLIANT + std::isdigit(l1); // NON_COMPLIANT + std::isgraph(l1); // NON_COMPLIANT + std::islower(l1); // NON_COMPLIANT + std::isprint(l1); // NON_COMPLIANT + std::ispunct(l1); // NON_COMPLIANT + std::isspace(l1); // NON_COMPLIANT + std::isupper(l1); // NON_COMPLIANT + std::isxdigit(l1); // NON_COMPLIANT + + // Character case mapping functions from + std::tolower(l1); // NON_COMPLIANT + std::toupper(l1); // NON_COMPLIANT +} + +void test_ctype_h_functions() { + char l1 = 'A'; + + // Character classification functions from + isalnum(l1); // NON_COMPLIANT + isalpha(l1); // NON_COMPLIANT + isblank(l1); // NON_COMPLIANT + iscntrl(l1); // NON_COMPLIANT + isdigit(l1); // NON_COMPLIANT + isgraph(l1); // NON_COMPLIANT + islower(l1); // NON_COMPLIANT + isprint(l1); // NON_COMPLIANT + ispunct(l1); // NON_COMPLIANT + isspace(l1); // NON_COMPLIANT + isupper(l1); // NON_COMPLIANT + isxdigit(l1); // NON_COMPLIANT + + // Character case mapping functions from + tolower(l1); // NON_COMPLIANT + toupper(l1); // NON_COMPLIANT +} + +void test_cwctype_functions() { + wchar_t l1 = L'A'; + + // Wide character classification functions from + std::iswalnum(l1); // NON_COMPLIANT + std::iswalpha(l1); // NON_COMPLIANT + std::iswblank(l1); // NON_COMPLIANT + std::iswcntrl(l1); // NON_COMPLIANT + std::iswdigit(l1); // NON_COMPLIANT + std::iswgraph(l1); // NON_COMPLIANT + std::iswlower(l1); // NON_COMPLIANT + std::iswprint(l1); // NON_COMPLIANT + std::iswpunct(l1); // NON_COMPLIANT + std::iswspace(l1); // NON_COMPLIANT + std::iswupper(l1); // NON_COMPLIANT + std::iswxdigit(l1); // NON_COMPLIANT + + // Wide character case mapping functions from + std::towlower(l1); // NON_COMPLIANT + std::towupper(l1); // NON_COMPLIANT + + // Wide character type functions from + std::wctype("alpha"); // NON_COMPLIANT + std::iswctype(l1, std::wctype("alpha")); // NON_COMPLIANT + std::wctrans("tolower"); // NON_COMPLIANT + std::towctrans(l1, std::wctrans("tolower")); // NON_COMPLIANT +} + +void test_wctype_h_functions() { + wchar_t l1 = L'A'; + + // Wide character classification functions from + iswalnum(l1); // NON_COMPLIANT + iswalpha(l1); // NON_COMPLIANT + iswblank(l1); // NON_COMPLIANT + iswcntrl(l1); // NON_COMPLIANT + iswdigit(l1); // NON_COMPLIANT + iswgraph(l1); // NON_COMPLIANT + iswlower(l1); // NON_COMPLIANT + iswprint(l1); // NON_COMPLIANT + iswpunct(l1); // NON_COMPLIANT + iswspace(l1); // NON_COMPLIANT + iswupper(l1); // NON_COMPLIANT + iswxdigit(l1); // NON_COMPLIANT + + // Wide character case mapping functions from + towlower(l1); // NON_COMPLIANT + towupper(l1); // NON_COMPLIANT + + // Wide character type functions from + wctype("alpha"); // NON_COMPLIANT + iswctype(l1, wctype("alpha")); // NON_COMPLIANT + wctrans("tolower"); // NON_COMPLIANT + towctrans(l1, wctrans("tolower")); // NON_COMPLIANT +} + +void test_function_addresses() { + // Taking addresses of functions from + int (*l1)(int) = &std::isalnum; // NON_COMPLIANT + int (*l2)(int) = &std::isalpha; // NON_COMPLIANT + int (*l3)(int) = &std::isblank; // NON_COMPLIANT + int (*l4)(int) = &std::iscntrl; // NON_COMPLIANT + int (*l5)(int) = &std::isdigit; // NON_COMPLIANT + int (*l6)(int) = &std::isgraph; // NON_COMPLIANT + int (*l7)(int) = &std::islower; // NON_COMPLIANT + int (*l8)(int) = &std::isprint; // NON_COMPLIANT + int (*l9)(int) = &std::ispunct; // NON_COMPLIANT + int (*l10)(int) = &std::isspace; // NON_COMPLIANT + int (*l11)(int) = &std::isupper; // NON_COMPLIANT + int (*l12)(int) = &std::isxdigit; // NON_COMPLIANT + int (*l13)(int) = &std::tolower; // NON_COMPLIANT + int (*l14)(int) = &std::toupper; // NON_COMPLIANT + + // Taking addresses of functions from + int (*l15)(int) = &isalnum; // NON_COMPLIANT + int (*l16)(int) = &isalpha; // NON_COMPLIANT + int (*l17)(int) = &isblank; // NON_COMPLIANT + int (*l18)(int) = &iscntrl; // NON_COMPLIANT + int (*l19)(int) = &isdigit; // NON_COMPLIANT + int (*l20)(int) = &isgraph; // NON_COMPLIANT + int (*l21)(int) = &islower; // NON_COMPLIANT + int (*l22)(int) = &isprint; // NON_COMPLIANT + int (*l23)(int) = &ispunct; // NON_COMPLIANT + int (*l24)(int) = &isspace; // NON_COMPLIANT + int (*l25)(int) = &isupper; // NON_COMPLIANT + int (*l26)(int) = &isxdigit; // NON_COMPLIANT + int (*l27)(int) = &tolower; // NON_COMPLIANT + int (*l28)(int) = &toupper; // NON_COMPLIANT + + // Taking addresses of functions from + int (*l29)(wint_t) = &std::iswalnum; // NON_COMPLIANT + int (*l30)(wint_t) = &std::iswalpha; // NON_COMPLIANT + int (*l31)(wint_t) = &std::iswblank; // NON_COMPLIANT + int (*l32)(wint_t) = &std::iswcntrl; // NON_COMPLIANT + int (*l33)(wint_t) = &std::iswdigit; // NON_COMPLIANT + int (*l34)(wint_t) = &std::iswgraph; // NON_COMPLIANT + int (*l35)(wint_t) = &std::iswlower; // NON_COMPLIANT + int (*l36)(wint_t) = &std::iswprint; // NON_COMPLIANT + int (*l37)(wint_t) = &std::iswpunct; // NON_COMPLIANT + int (*l38)(wint_t) = &std::iswspace; // NON_COMPLIANT + int (*l39)(wint_t) = &std::iswupper; // NON_COMPLIANT + int (*l40)(wint_t) = &std::iswxdigit; // NON_COMPLIANT + wint_t (*l41)(wint_t) = &std::towlower; // NON_COMPLIANT + wint_t (*l42)(wint_t) = &std::towupper; // NON_COMPLIANT + wctype_t (*l43)(const char *) = &std::wctype; // NON_COMPLIANT + int (*l44)(wint_t, wctype_t) = &std::iswctype; // NON_COMPLIANT + wctrans_t (*l45)(const char *) = &std::wctrans; // NON_COMPLIANT + wint_t (*l46)(wint_t, wctrans_t) = &std::towctrans; // NON_COMPLIANT + + // Taking addresses of functions from + int (*l47)(wint_t) = &iswalnum; // NON_COMPLIANT + int (*l48)(wint_t) = &iswalpha; // NON_COMPLIANT + int (*l49)(wint_t) = &iswblank; // NON_COMPLIANT + int (*l50)(wint_t) = &iswcntrl; // NON_COMPLIANT + int (*l51)(wint_t) = &iswdigit; // NON_COMPLIANT + int (*l52)(wint_t) = &iswgraph; // NON_COMPLIANT + int (*l53)(wint_t) = &iswlower; // NON_COMPLIANT + int (*l54)(wint_t) = &iswprint; // NON_COMPLIANT + int (*l55)(wint_t) = &iswpunct; // NON_COMPLIANT + int (*l56)(wint_t) = &iswspace; // NON_COMPLIANT + int (*l57)(wint_t) = &iswupper; // NON_COMPLIANT + int (*l58)(wint_t) = &iswxdigit; // NON_COMPLIANT + wint_t (*l59)(wint_t) = &towlower; // NON_COMPLIANT + wint_t (*l60)(wint_t) = &towupper; // NON_COMPLIANT + wctype_t (*l61)(const char *) = &wctype; // NON_COMPLIANT + int (*l62)(wint_t, wctype_t) = &iswctype; // NON_COMPLIANT + wctrans_t (*l63)(const char *) = &wctrans; // NON_COMPLIANT + wint_t (*l64)(wint_t, wctrans_t) = &towctrans; // NON_COMPLIANT +} + +void test_compliant_locale_usage() { + char l1 = 'A'; + wchar_t l2 = L'A'; + std::locale l3{}; + + // Compliant usage with locale parameter + std::isalnum(l1, l3); // COMPLIANT + std::isalpha(l1, l3); // COMPLIANT + std::isblank(l1, l3); // COMPLIANT + std::iscntrl(l1, l3); // COMPLIANT + std::isdigit(l1, l3); // COMPLIANT + std::isgraph(l1, l3); // COMPLIANT + std::islower(l1, l3); // COMPLIANT + std::isprint(l1, l3); // COMPLIANT + std::ispunct(l1, l3); // COMPLIANT + std::isspace(l1, l3); // COMPLIANT + std::isupper(l1, l3); // COMPLIANT + std::isxdigit(l1, l3); // COMPLIANT + + std::tolower(l1, l3); // COMPLIANT + std::toupper(l1, l3); // COMPLIANT + + // Compliant wide character usage with locale parameter + std::isalnum(l2, l3); // COMPLIANT + std::isalpha(l2, l3); // COMPLIANT + std::isblank(l2, l3); // COMPLIANT + std::iscntrl(l2, l3); // COMPLIANT + std::isdigit(l2, l3); // COMPLIANT + std::isgraph(l2, l3); // COMPLIANT + std::islower(l2, l3); // COMPLIANT + std::isprint(l2, l3); // COMPLIANT + std::ispunct(l2, l3); // COMPLIANT + std::isspace(l2, l3); // COMPLIANT + std::isupper(l2, l3); // COMPLIANT + std::isxdigit(l2, l3); // COMPLIANT + + std::tolower(l2, l3); // COMPLIANT + std::toupper(l2, l3); // COMPLIANT +} \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.expected b/cpp/misra/test/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.expected new file mode 100644 index 0000000000..49ce89347c --- /dev/null +++ b/cpp/misra/test/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.expected @@ -0,0 +1,23 @@ +| test.cpp:9:3:9:8 | call to memcpy | Call to banned function 'memcpy' from . | +| test.cpp:10:3:10:13 | call to memcpy | Call to banned function 'memcpy' from . | +| test.cpp:17:3:17:9 | call to memmove | Call to banned function 'memmove' from . | +| test.cpp:18:3:18:14 | call to memmove | Call to banned function 'memmove' from . | +| test.cpp:25:12:25:17 | call to memcmp | Call to banned function 'memcmp' from . | +| test.cpp:26:12:26:22 | call to memcmp | Call to banned function 'memcmp' from . | +| test.cpp:30:52:30:57 | memcpy | Address taken for banned function 'memcpy' from . | +| test.cpp:31:52:31:58 | memmove | Address taken for banned function 'memmove' from . | +| test.cpp:32:56:32:61 | memcmp | Address taken for banned function 'memcmp' from . | +| test.cpp:34:52:34:62 | memcpy | Address taken for banned function 'memcpy' from . | +| test.cpp:36:7:36:18 | memmove | Address taken for banned function 'memmove' from . | +| test.cpp:38:7:38:17 | memcmp | Address taken for banned function 'memcmp' from . | +| test.cpp:50:7:50:12 | call to memcmp | Call to banned function 'memcmp' from . | +| test.cpp:53:7:53:17 | call to memcmp | Call to banned function 'memcmp' from . | +| test.cpp:61:7:61:12 | call to memcmp | Call to banned function 'memcmp' from . | +| test.cpp:64:7:64:17 | call to memcmp | Call to banned function 'memcmp' from . | +| test.cpp:71:3:71:8 | call to memcpy | Call to banned function 'memcpy' from . | +| test.cpp:72:3:72:9 | call to memmove | Call to banned function 'memmove' from . | +| test.cpp:74:3:74:13 | call to memcpy | Call to banned function 'memcpy' from . | +| test.cpp:75:3:75:14 | call to memmove | Call to banned function 'memmove' from . | +| test.cpp:78:1:78:28 | #define CUSTOM_MEMCPY memcpy | Call to banned function 'memcpy' from . | +| test.cpp:79:1:79:30 | #define CUSTOM_MEMMOVE memmove | Call to banned function 'memmove' from . | +| test.cpp:80:1:80:28 | #define CUSTOM_MEMCMP memcmp | Call to banned function 'memcmp' from . | diff --git a/cpp/misra/test/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.qlref b/cpp/misra/test/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.qlref new file mode 100644 index 0000000000..53307ad85f --- /dev/null +++ b/cpp/misra/test/rules/RULE-24-5-2/NoMemoryFunctionsFromCString.qlref @@ -0,0 +1 @@ +rules/RULE-24-5-2/NoMemoryFunctionsFromCString.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-24-5-2/test.cpp b/cpp/misra/test/rules/RULE-24-5-2/test.cpp new file mode 100644 index 0000000000..f189afdbc6 --- /dev/null +++ b/cpp/misra/test/rules/RULE-24-5-2/test.cpp @@ -0,0 +1,89 @@ +#include +#include +#include + +void test_memcpy_usage() { + std::uint8_t l1[10]; + std::uint8_t l2[10]; + + memcpy(l1, l2, 10); // NON_COMPLIANT + std::memcpy(l1, l2, 10); // NON_COMPLIANT +} + +void test_memmove_usage() { + std::uint8_t l1[10]; + std::uint8_t l2[10]; + + memmove(l1, l2, 10); // NON_COMPLIANT + std::memmove(l1, l2, 10); // NON_COMPLIANT +} + +void test_memcmp_usage() { + std::uint8_t l1[10]; + std::uint8_t l2[10]; + + int l3 = memcmp(l1, l2, 10); // NON_COMPLIANT + int l4 = std::memcmp(l1, l2, 10); // NON_COMPLIANT +} + +void test_function_pointers() { + void *(*l1)(void *, const void *, std::size_t) = memcpy; // NON_COMPLIANT + void *(*l2)(void *, const void *, std::size_t) = memmove; // NON_COMPLIANT + int (*l3)(const void *, const void *, std::size_t) = memcmp; // NON_COMPLIANT + + void *(*l4)(void *, const void *, std::size_t) = std::memcpy; // NON_COMPLIANT + void *(*l5)(void *, const void *, std::size_t) = + std::memmove; // NON_COMPLIANT + int (*l6)(const void *, const void *, std::size_t) = + std::memcmp; // NON_COMPLIANT +} + +struct S { + bool m1; + std::int64_t m2; +}; + +void test_struct_comparison() { + S l1{true, 42}; + S l2{true, 42}; + + if (memcmp(&l1, &l2, sizeof(S)) != 0) { // NON_COMPLIANT + } + + if (std::memcmp(&l1, &l2, sizeof(S)) != 0) { // NON_COMPLIANT + } +} + +void test_buffer_comparison() { + char l1[12]; + char l2[12]; + + if (memcmp(l1, l2, sizeof(l1)) != 0) { // NON_COMPLIANT + } + + if (std::memcmp(l1, l2, sizeof(l1)) != 0) { // NON_COMPLIANT + } +} + +void test_overlapping_memory() { + std::uint8_t l1[20]; + + memcpy(l1 + 5, l1, 10); // NON_COMPLIANT + memmove(l1 + 5, l1, 10); // NON_COMPLIANT + + std::memcpy(l1 + 5, l1, 10); // NON_COMPLIANT + std::memmove(l1 + 5, l1, 10); // NON_COMPLIANT +} + +#define CUSTOM_MEMCPY memcpy // NON_COMPLIANT +#define CUSTOM_MEMMOVE memmove // NON_COMPLIANT +#define CUSTOM_MEMCMP memcmp // NON_COMPLIANT + +void test_macro_expansion() { + std::uint8_t l1[10]; + std::uint8_t l2[10]; + + CUSTOM_MEMCPY(l1, l2, 10); + CUSTOM_MEMMOVE(l1, l2, 10); + int l3 = CUSTOM_MEMCMP(l1, l2, 10); +} \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.expected b/cpp/misra/test/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.expected new file mode 100644 index 0000000000..fde7f610e8 --- /dev/null +++ b/cpp/misra/test/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.expected @@ -0,0 +1,9 @@ +| test.cpp:6:3:6:16 | call to setlocale | Call to banned function 'setlocale' from . | +| test.cpp:7:3:7:16 | call to setlocale | Call to banned function 'setlocale' from . | +| test.cpp:8:3:8:16 | call to setlocale | Call to banned function 'setlocale' from . | +| test.cpp:12:3:12:21 | call to global | Call to banned function 'global' from . | +| test.cpp:13:3:13:21 | call to global | Call to banned function 'global' from . | +| test.cpp:36:5:36:18 | call to setlocale | Call to banned function 'setlocale' from . | +| test.cpp:40:5:40:18 | call to setlocale | Call to banned function 'setlocale' from . | +| test.cpp:45:3:45:21 | call to global | Call to banned function 'global' from . | +| test.cpp:46:3:46:21 | call to global | Call to banned function 'global' from . | diff --git a/cpp/misra/test/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.qlref b/cpp/misra/test/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.qlref new file mode 100644 index 0000000000..f28199a5aa --- /dev/null +++ b/cpp/misra/test/rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.qlref @@ -0,0 +1 @@ +rules/RULE-25-5-1/LocaleGlobalFunctionNotAllowed.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-25-5-1/test.cpp b/cpp/misra/test/rules/RULE-25-5-1/test.cpp new file mode 100644 index 0000000000..b45be36f70 --- /dev/null +++ b/cpp/misra/test/rules/RULE-25-5-1/test.cpp @@ -0,0 +1,47 @@ +#include +#include +#include + +void test_setlocale_call() { + std::setlocale(LC_ALL, "C"); // NON_COMPLIANT + std::setlocale(LC_NUMERIC, "C"); // NON_COMPLIANT + std::setlocale(LC_TIME, "en_US.UTF-8"); // NON_COMPLIANT +} + +void test_locale_global_call() { + std::locale::global(std::locale("C")); // NON_COMPLIANT + std::locale::global(std::locale::classic()); // NON_COMPLIANT +} + +void test_compliant_locale_usage() { + wchar_t l1 = L'\u2002'; + std::locale l2("C"); + + if (std::isspace(l1, l2)) { // COMPLIANT + } + if (std::isalpha(l1, l2)) { // COMPLIANT + } + if (std::isdigit(l1, l2)) { // COMPLIANT + } +} + +void test_compliant_locale_construction() { + std::locale l3("C"); // COMPLIANT + std::locale l4 = std::locale::classic(); // COMPLIANT + std::locale l5; // COMPLIANT +} + +void test_nested_setlocale_calls() { + if (true) { + std::setlocale(LC_ALL, "ja_JP.utf8"); // NON_COMPLIANT + } + + for (int l6 = 0; l6 < 1; ++l6) { + std::setlocale(LC_CTYPE, "C"); // NON_COMPLIANT + } +} + +void test_locale_global_with_different_locales() { + std::locale::global(std::locale("en_US.UTF-8")); // NON_COMPLIANT + std::locale::global(std::locale("ja_JP.utf8")); // NON_COMPLIANT +} \ No newline at end of file diff --git a/rule_packages/cpp/BannedAPIs.json b/rule_packages/cpp/BannedAPIs.json new file mode 100644 index 0000000000..591f50b5e6 --- /dev/null +++ b/rule_packages/cpp/BannedAPIs.json @@ -0,0 +1,184 @@ +{ + "MISRA-C++-2023": { + "RULE-18-5-2": { + "properties": { + "enforcement": "decidable", + "obligation": "advisory" + }, + "queries": [ + { + "description": "Using program-terminating functions like abort, exit, _Exit, quick_exit or terminate causes the stack to not be unwound and object destructors to not be called, potentially leaving the environment in an undesirable state.", + "kind": "problem", + "name": "Program-terminating functions should not be used", + "precision": "very-high", + "severity": "error", + "short_name": "AvoidProgramTerminatingFunctions", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "Program-terminating functions should not be used" + }, + "RULE-21-10-1": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Using features like va_list, va_arg, va_start, va_end and va_copy bypasses compiler type checking and leads to undefined behavior when used incorrectly.", + "kind": "problem", + "name": "The features of shall not be used", + "precision": "very-high", + "severity": "error", + "short_name": "NoVariadicFunctionMacros", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The features of shall not be used" + }, + "RULE-21-10-2": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Using facilities from the header causes undefined behavior by bypassing normal function return mechanisms and may result in non-trivial object destruction being omitted.", + "kind": "problem", + "name": "The standard header file shall not be used", + "precision": "very-high", + "severity": "error", + "short_name": "NoCsetjmpHeader", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The standard header file shall not be used" + }, + "RULE-21-2-2": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Using string handling functions from , , and headers may result in buffer overflows or unreliable error detection through errno.", + "kind": "problem", + "name": "The string handling functions from , , and shall not be used", + "precision": "very-high", + "severity": "error", + "short_name": "UnsafeStringHandlingFunctions", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The string handling functions from , , and shall not be used" + }, + "RULE-21-2-3": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Using the system() function from cstdlib or stdlib.h causes undefined behavior and potential security vulnerabilities.", + "kind": "problem", + "name": "The library function system from shall not be used", + "precision": "very-high", + "severity": "error", + "short_name": "BannedSystemFunction", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The library function system from shall not be used" + }, + "RULE-23-11-1": { + "properties": { + "enforcement": "decidable", + "obligation": "advisory" + }, + "queries": [ + { + "description": "Using raw pointer constructors of std::shared_ptr and std::unique_ptr instead of make_shared/make_unique can lead to memory leaks if exceptions occur during construction.", + "kind": "problem", + "name": "The raw pointer constructors of std::shared_ptr and std::unique_ptr should not be used", + "precision": "very-high", + "severity": "error", + "short_name": "UseSmartPtrFactoryFunctions", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The raw pointer constructors of std::shared_ptr and std::unique_ptr should not be used" + }, + "RULE-24-5-1": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Using character classification and case mapping functions from and causes undefined behavior when arguments are not representable as unsigned char or not equal to EOF.", + "kind": "problem", + "name": "The character handling functions from and shall not be used", + "precision": "very-high", + "severity": "error", + "short_name": "CharacterHandlingFunctionRestrictions", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The character handling functions from and shall not be used" + }, + "RULE-24-5-2": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Using memcpy, memmove or memcmp from can result in undefined behavior due to overlapping memory, non-trivially copyable objects, or unequal comparison of logically equal objects.", + "kind": "problem", + "name": "The C++ Standard Library functions memcpy, memmove and memcmp from shall not be used", + "precision": "very-high", + "severity": "error", + "short_name": "NoMemoryFunctionsFromCString", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The C++ Standard Library functions memcpy, memmove and memcmp from shall not be used" + }, + "RULE-25-5-1": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Calling setlocale or std::locale::global functions can introduce data races with functions that use the locale, leading to undefined behavior.", + "kind": "problem", + "name": "The setlocale and std::locale::global functions shall not be called", + "precision": "very-high", + "severity": "error", + "short_name": "LocaleGlobalFunctionNotAllowed", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The setlocale and std::locale::global functions shall not be called" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index 68049625e6..0af18d1f20 100644 --- a/rules.csv +++ b/rules.csv @@ -869,7 +869,7 @@ cpp,MISRA-C++-2023,RULE-6-8-2,Yes,Mandatory,Decidable,Single Translation Unit,A cpp,MISRA-C++-2023,RULE-6-8-3,Yes,Required,Decidable,Single Translation Unit,An assignment operator shall not assign the address of an object with automatic storage duration to an object with a greater lifetime,,Lifetime,Medium, cpp,MISRA-C++-2023,RULE-6-8-4,Yes,Advisory,Decidable,Single Translation Unit,Member functions returning references to their object should be refqualified appropriately,,Declarations2,Medium, cpp,MISRA-C++-2023,RULE-6-9-1,Yes,Required,Decidable,Single Translation Unit,The same type aliases shall be used in all declarations of the same entity,,Declarations2,Medium, -cpp,MISRA-C++-2023,RULE-6-9-2,Yes,Advisory,Decidable,Single Translation Unit,The names of the standard signed integer types and standard unsigned integer types should not be used,A3-9-1,BannedAPIs,Easy, +cpp,MISRA-C++-2023,RULE-6-9-2,Yes,Advisory,Decidable,Single Translation Unit,The names of the standard signed integer types and standard unsigned integer types should not be used,A3-9-1,FixedWithInt,Easy, cpp,MISRA-C++-2023,RULE-7-0-1,Yes,Required,Decidable,Single Translation Unit,There shall be no conversion from type bool,,Conversions,Easy, cpp,MISRA-C++-2023,RULE-7-0-2,Yes,Required,Decidable,Single Translation Unit,There shall be no conversion to type bool,,Conversions,Easy, cpp,MISRA-C++-2023,RULE-7-0-3,Yes,Required,Decidable,Single Translation Unit,The numerical value of a character shall not be used,M5-0-11,Conversions,Medium,