diff --git a/change_notes/2025-06-10-a3-9-1-functions.md b/change_notes/2025-06-10-a3-9-1-functions.md new file mode 100644 index 0000000000..8366d2172f --- /dev/null +++ b/change_notes/2025-06-10-a3-9-1-functions.md @@ -0,0 +1,2 @@ + - `A3-9-1` - `VariableWidthIntegerTypesUsed.ql`: + - This query now reports the use of non-fixed width integer types in function return types, with the exception of `char` types and for `main` functions. \ No newline at end of file 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/autosar/src/rules/A3-9-1/VariableWidthIntegerTypesUsed.ql b/cpp/autosar/src/rules/A3-9-1/VariableWidthIntegerTypesUsed.ql index fa19ad998f..dfc73cebc8 100644 --- a/cpp/autosar/src/rules/A3-9-1/VariableWidthIntegerTypesUsed.ql +++ b/cpp/autosar/src/rules/A3-9-1/VariableWidthIntegerTypesUsed.ql @@ -17,26 +17,10 @@ import cpp import codingstandards.cpp.autosar -import codingstandards.cpp.EncapsulatingFunctions -import codingstandards.cpp.BuiltInNumericTypes -import codingstandards.cpp.Type -import codingstandards.cpp.Operator +import codingstandards.cpp.rules.variablewidthintegertypesused.VariableWidthIntegerTypesUsed -from Variable v, Type typeStrippedOfSpecifiers -where - not isExcluded(v, DeclarationsPackage::variableWidthIntegerTypesUsedQuery()) and - typeStrippedOfSpecifiers = stripSpecifiers(v.getType()) and - ( - typeStrippedOfSpecifiers instanceof BuiltInIntegerType or - typeStrippedOfSpecifiers instanceof UnsignedCharType or - typeStrippedOfSpecifiers instanceof SignedCharType - ) and - not v instanceof ExcludedVariable and - // Dont consider template instantiations because instantiations with - // Fixed Width Types are recorded after stripping their typedef'd type, - // thereby, causing false positives (#540). - not v.isFromTemplateInstantiation(_) and - //post-increment/post-decrement operators are required by the standard to have a dummy int parameter - not v.(Parameter).getFunction() instanceof PostIncrementOperator and - not v.(Parameter).getFunction() instanceof PostDecrementOperator -select v, "Variable '" + v.getName() + "' has variable-width type." +class VariableWidthIntegerTypesUsedQuery extends VariableWidthIntegerTypesUsedSharedQuery { + VariableWidthIntegerTypesUsedQuery() { + this = DeclarationsPackage::variableWidthIntegerTypesUsedQuery() + } +} diff --git a/cpp/autosar/test/rules/A3-9-1/VariableWidthIntegerTypesUsed.qlref b/cpp/autosar/test/rules/A3-9-1/VariableWidthIntegerTypesUsed.qlref deleted file mode 100644 index 797bbacc94..0000000000 --- a/cpp/autosar/test/rules/A3-9-1/VariableWidthIntegerTypesUsed.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A3-9-1/VariableWidthIntegerTypesUsed.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A3-9-1/VariableWidthIntegerTypesUsed.testref b/cpp/autosar/test/rules/A3-9-1/VariableWidthIntegerTypesUsed.testref new file mode 100644 index 0000000000..bb41437be6 --- /dev/null +++ b/cpp/autosar/test/rules/A3-9-1/VariableWidthIntegerTypesUsed.testref @@ -0,0 +1 @@ +cpp/common/test/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A3-9-1/VariableWidthPlainCharTypeUsed.expected b/cpp/autosar/test/rules/A3-9-1/VariableWidthPlainCharTypeUsed.expected index 6631606cbf..8602920f1e 100644 --- a/cpp/autosar/test/rules/A3-9-1/VariableWidthPlainCharTypeUsed.expected +++ b/cpp/autosar/test/rules/A3-9-1/VariableWidthPlainCharTypeUsed.expected @@ -1,3 +1,3 @@ | test.cpp:4:8:4:8 | c | Variable 'c' has variable-width char type. | -| test.cpp:38:14:38:15 | c1 | Variable 'c1' has variable-width char type. | -| test.cpp:56:17:56:18 | c2 | Variable 'c2' has variable-width char type. | +| test.cpp:10:14:10:15 | c1 | Variable 'c1' has variable-width char type. | +| test.cpp:14:17:14:18 | c2 | Variable 'c2' has variable-width char type. | diff --git a/cpp/autosar/test/rules/A3-9-1/test.cpp b/cpp/autosar/test/rules/A3-9-1/test.cpp index 7ffb87ca39..96ef45142f 100644 --- a/cpp/autosar/test/rules/A3-9-1/test.cpp +++ b/cpp/autosar/test/rules/A3-9-1/test.cpp @@ -2,88 +2,16 @@ void test_variable_width_type_variables() { char c; // NON_COMPLIANT - unsigned char uc; // NON_COMPLIANT - signed char sc; // NON_COMPLIANT - - int i; // NON_COMPLIANT - unsigned int ui; // NON_COMPLIANT - unsigned u; // NON_COMPLIANT - signed int si; // NON_COMPLIANT - signed s; // NON_COMPLIANT - - short sh; // NON_COMPLIANT - unsigned short ush; // NON_COMPLIANT - signed short ssh; // NON_COMPLIANT - - long l; // NON_COMPLIANT - unsigned long ul; // NON_COMPLIANT - signed long sl; // NON_COMPLIANT - - std::int8_t i8; // COMPLIANT - std::int16_t i16; // COMPLIANT - std::int32_t i32; // COMPLIANT - std::int64_t i64; // COMPLIANT - - std::uint8_t u8; // COMPLIANT - std::uint16_t u16; // COMPLIANT - std::uint32_t u32; // COMPLIANT - std::uint64_t u64; // COMPLIANT -} - -int main(int argc, char *argv[]) { // COMPLIANT - // main as an exception + unsigned char uc; // COMPLIANT - covered by VariableWidthIntegerTypesUsed + signed char sc; // COMPLIANT - covered by VariableWidthIntegerTypesUsed } void test_variable_width_type_qualified_variables() { const char c1 = 0; // NON_COMPLIANT - const unsigned char uc1 = 0; // NON_COMPLIANT - const signed char sc1 = 0; // NON_COMPLIANt - - const int i1 = 0; // NON_COMPLIANT - const unsigned int ui1 = 0; // NON_COMPLIANT - const unsigned u1 = 0; // NON_COMPLIANT - const signed int si1 = 0; // NON_COMPLIANT - const signed s1 = 0; // NON_COMPLIANT - - const short sh1 = 0; // NON_COMPLIANT - const unsigned short ush1 = 0; // NON_COMPLIANT - const signed short ssh1 = 0; // NON_COMPLIANT - - const long l1 = 0; // NON_COMPLIANT - const unsigned long ul1 = 0; // NON_COMPLIANT - const signed long sl1 = 0; // NON_COMPLIANT + const unsigned char uc1 = 0; // COMPLIANT - (VariableWidthIntegerTypesUsed) + const signed char sc1 = 0; // COMPLIANT - (VariableWidthIntegerTypesUsed) volatile char c2; // NON_COMPLIANT - volatile unsigned char uc2; // NON_COMPLIANT - volatile signed char sc2; // NON_COMPLIANt - - volatile int i2; // NON_COMPLIANT - volatile unsigned int ui2; // NON_COMPLIANT - volatile unsigned u2; // NON_COMPLIANT - volatile signed int si2; // NON_COMPLIANT - volatile signed s2; // NON_COMPLIANT - - volatile short sh2; // NON_COMPLIANT - volatile unsigned short ush2; // NON_COMPLIANT - volatile signed short ssh2; // NON_COMPLIANT - - volatile long l2; // NON_COMPLIANT - volatile unsigned long ul2; // NON_COMPLIANT - volatile signed long sl2; // NON_COMPLIANT -} - -struct test_fix_fp_614 { - test_fix_fp_614 operator++(int); // COMPLIANT - test_fix_fp_614 operator--(int); // COMPLIANT -}; - -// COMPLIANT - instantiated with Fixed Width Types. -template constexpr void test_fix_fp_540(MyType value) { - value++; -} - -int call_test_fix_fp_540() { - test_fix_fp_540(19); - test_fix_fp_540(20); - return 0; -} + volatile unsigned char uc2; // COMPLIANT - (VariableWidthIntegerTypesUsed) + volatile signed char sc2; // COMPLIANT - (VariableWidthIntegerTypesUsed) +} \ No newline at end of file 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/BuiltInNumericTypes.qll b/cpp/common/src/codingstandards/cpp/BuiltInNumericTypes.qll index b145428a57..b156930810 100644 --- a/cpp/common/src/codingstandards/cpp/BuiltInNumericTypes.qll +++ b/cpp/common/src/codingstandards/cpp/BuiltInNumericTypes.qll @@ -20,3 +20,10 @@ class BuiltInIntegerType extends BuiltInType { class ExcludedVariable extends Parameter { ExcludedVariable() { getFunction() instanceof MainFunction } } + +/** + * Any main function. + */ +class ExcludedFunction extends Function { + ExcludedFunction() { this instanceof MainFunction } +} 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..ea4f78841b --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedAPIs.qll @@ -0,0 +1,180 @@ +//** 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() or + TAvoidStandardIntegerTypeNamesQuery() + +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" + or + query = + // `Query` instance for the `avoidStandardIntegerTypeNames` query + BannedAPIsPackage::avoidStandardIntegerTypeNamesQuery() and + queryId = + // `@id` for the `avoidStandardIntegerTypeNames` query + "cpp/misra/avoid-standard-integer-type-names" and + ruleId = "RULE-6-9-2" and + category = "advisory" +} + +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())) + } + + Query avoidStandardIntegerTypeNamesQuery() { + //autogenerate `Query` type + result = + // `Query` type for `avoidStandardIntegerTypeNames` query + TQueryCPP(TBannedAPIsPackageQuery(TAvoidStandardIntegerTypeNamesQuery())) + } +} 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/src/codingstandards/cpp/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.qll b/cpp/common/src/codingstandards/cpp/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.qll new file mode 100644 index 0000000000..047d501a22 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.qll @@ -0,0 +1,52 @@ +/** + * Provides a library with a `problems` predicate for the following issue: + * The basic numerical types of signed/unsigned char, int, short, long are not supposed + * to be used. The specific-length types from header need be used instead. + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import codingstandards.cpp.EncapsulatingFunctions +import codingstandards.cpp.BuiltInNumericTypes +import codingstandards.cpp.Type +import codingstandards.cpp.Operator + +abstract class VariableWidthIntegerTypesUsedSharedQuery extends Query { } + +Query getQuery() { result instanceof VariableWidthIntegerTypesUsedSharedQuery } + +query predicate problems(Element e, string message) { + not isExcluded(e, getQuery()) and + exists(Type typeStrippedOfSpecifiers, Type rawType | + typeStrippedOfSpecifiers = stripSpecifiers(rawType) and + ( + typeStrippedOfSpecifiers instanceof BuiltInIntegerType or + typeStrippedOfSpecifiers instanceof UnsignedCharType or + typeStrippedOfSpecifiers instanceof SignedCharType + ) + | + exists(Variable v | v = e | + v.getType() = rawType and + not v instanceof ExcludedVariable and + // Dont consider template instantiations because instantiations with + // Fixed Width Types are recorded after stripping their typedef'd type, + // thereby, causing false positives (#540). + not v.isFromTemplateInstantiation(_) and + //post-increment/post-decrement operators are required by the standard to have a dummy int parameter + not v.(Parameter).getFunction() instanceof PostIncrementOperator and + not v.(Parameter).getFunction() instanceof PostDecrementOperator and + message = "Variable '" + v.getName() + "' has variable-width type." + ) + or + exists(Function f | f = e | + f.getType() = rawType and + not f instanceof ExcludedFunction and + // Dont consider template instantiations because instantiations with + // Fixed Width Types are recorded after stripping their typedef'd type, + // thereby, causing false positives (#540). + not f.isFromTemplateInstantiation(_) and + message = "Function '" + f.getName() + "' has variable-width return type." + ) + ) +} 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/autosar/test/rules/A3-9-1/VariableWidthIntegerTypesUsed.expected b/cpp/common/test/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.expected similarity index 100% rename from cpp/autosar/test/rules/A3-9-1/VariableWidthIntegerTypesUsed.expected rename to cpp/common/test/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.expected diff --git a/cpp/common/test/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.ql b/cpp/common/test/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.ql new file mode 100644 index 0000000000..1c86ca86d7 --- /dev/null +++ b/cpp/common/test/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.ql @@ -0,0 +1,4 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.variablewidthintegertypesused.VariableWidthIntegerTypesUsed + +class TestFileQuery extends VariableWidthIntegerTypesUsedSharedQuery, TestQuery { } diff --git a/cpp/common/test/rules/variablewidthintegertypesused/test.cpp b/cpp/common/test/rules/variablewidthintegertypesused/test.cpp new file mode 100644 index 0000000000..bee63342e2 --- /dev/null +++ b/cpp/common/test/rules/variablewidthintegertypesused/test.cpp @@ -0,0 +1,155 @@ +#include + +void test_variable_width_type_variables() { + char c; // COMPLIANT + unsigned char uc; // NON_COMPLIANT + signed char sc; // NON_COMPLIANT + + int i; // NON_COMPLIANT + unsigned int ui; // NON_COMPLIANT + unsigned u; // NON_COMPLIANT + signed int si; // NON_COMPLIANT + signed s; // NON_COMPLIANT + + short sh; // NON_COMPLIANT + unsigned short ush; // NON_COMPLIANT + signed short ssh; // NON_COMPLIANT + + long l; // NON_COMPLIANT + unsigned long ul; // NON_COMPLIANT + signed long sl; // NON_COMPLIANT + + std::int8_t i8; // COMPLIANT + std::int16_t i16; // COMPLIANT + std::int32_t i32; // COMPLIANT + std::int64_t i64; // COMPLIANT + + std::uint8_t u8; // COMPLIANT + std::uint16_t u16; // COMPLIANT + std::uint32_t u32; // COMPLIANT + std::uint64_t u64; // COMPLIANT +} + +int main(int argc, char *argv[]) { // COMPLIANT + // main as an exception +} + +void test_variable_width_type_qualified_variables() { + const char c1 = 0; // COMPLIANT + const unsigned char uc1 = 0; // NON_COMPLIANT + const signed char sc1 = 0; // NON_COMPLIANt + + const int i1 = 0; // NON_COMPLIANT + const unsigned int ui1 = 0; // NON_COMPLIANT + const unsigned u1 = 0; // NON_COMPLIANT + const signed int si1 = 0; // NON_COMPLIANT + const signed s1 = 0; // NON_COMPLIANT + + const short sh1 = 0; // NON_COMPLIANT + const unsigned short ush1 = 0; // NON_COMPLIANT + const signed short ssh1 = 0; // NON_COMPLIANT + + const long l1 = 0; // NON_COMPLIANT + const unsigned long ul1 = 0; // NON_COMPLIANT + const signed long sl1 = 0; // NON_COMPLIANT + + volatile char c2; // COMPLIANT + volatile unsigned char uc2; // NON_COMPLIANT + volatile signed char sc2; // NON_COMPLIANt + + volatile int i2; // NON_COMPLIANT + volatile unsigned int ui2; // NON_COMPLIANT + volatile unsigned u2; // NON_COMPLIANT + volatile signed int si2; // NON_COMPLIANT + volatile signed s2; // NON_COMPLIANT + + volatile short sh2; // NON_COMPLIANT + volatile unsigned short ush2; // NON_COMPLIANT + volatile signed short ssh2; // NON_COMPLIANT + + volatile long l2; // NON_COMPLIANT + volatile unsigned long ul2; // NON_COMPLIANT + volatile signed long sl2; // NON_COMPLIANT +} + +struct test_fix_fp_614 { + test_fix_fp_614 operator++(int); // COMPLIANT + test_fix_fp_614 operator--(int); // COMPLIANT +}; + +// COMPLIANT - instantiated with Fixed Width Types. +template constexpr void test_fix_fp_540(MyType value) { + value++; +} + +void call_test_fix_fp_540() { + test_fix_fp_540(19); + test_fix_fp_540(20); +} + +char test_char_return() { // COMPLIANT + return 'a'; +} +unsigned char test_unsigned_char_return() { // NON_COMPLIANT + return 'b'; +} +signed char test_signed_char_return() { // NON_COMPLIANT + return 'c'; +} +int test_int_return() { // NON_COMPLIANT + return 42; +} +unsigned int test_unsigned_int_return() { // NON_COMPLIANT + return 43; +} +unsigned test_unsigned_return() { // NON_COMPLIANT + return 44; +} +signed int test_signed_int_return() { // NON_COMPLIANT + return 45; +} +signed test_signed_return() { // NON_COMPLIANT + return 46; +} +short test_short_return() { // NON_COMPLIANT + return 47; +} +unsigned short test_unsigned_short_return() { // NON_COMPLIANT + return 48; +} +signed short test_signed_short_return() { // NON_COMPLIANT + return 49; +} +long test_long_return() { // NON_COMPLIANT + return 50; +} +unsigned long test_unsigned_long_return() { // NON_COMPLIANT + return 51; +} +signed long test_signed_long_return() { // NON_COMPLIANT + return 52; +} +std::int8_t test_int8_t_return() { // COMPLIANT + return 53; +} +std::int16_t test_int16_t_return() { // COMPLIANT + return 54; +} +std::int32_t test_int32_t_return() { // COMPLIANT + return 55; +} +std::int64_t test_int64_t_return() { // COMPLIANT + return 56; +} +std::uint8_t test_uint8_t_return() { // COMPLIANT + return 57; +} +std::uint16_t test_uint16_t_return() { // COMPLIANT + return 58; +} +std::uint32_t test_uint32_t_return() { // COMPLIANT + return 59; +} +std::uint64_t test_uint64_t_return() { // COMPLIANT + return 60; +} 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/src/rules/RULE-6-9-2/AvoidStandardIntegerTypeNames.ql b/cpp/misra/src/rules/RULE-6-9-2/AvoidStandardIntegerTypeNames.ql new file mode 100644 index 0000000000..ef02deb899 --- /dev/null +++ b/cpp/misra/src/rules/RULE-6-9-2/AvoidStandardIntegerTypeNames.ql @@ -0,0 +1,23 @@ +/** + * @id cpp/misra/avoid-standard-integer-type-names + * @name RULE-6-9-2: The names of the standard signed integer types and standard unsigned integer types should not be + * @description Using standard signed and unsigned integer type names instead of specified width + * types makes storage requirements unclear and implementation-dependent. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-6-9-2 + * scope/single-translation-unit + * external/misra/enforcement/decidable + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra +import codingstandards.cpp.rules.variablewidthintegertypesused.VariableWidthIntegerTypesUsed + +class AvoidStandardIntegerTypeNamesQuery extends VariableWidthIntegerTypesUsedSharedQuery { + AvoidStandardIntegerTypeNamesQuery() { + this = BannedAPIsPackage::avoidStandardIntegerTypeNamesQuery() + } +} 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/cpp/misra/test/rules/RULE-6-9-2/AvoidStandardIntegerTypeNames.testref b/cpp/misra/test/rules/RULE-6-9-2/AvoidStandardIntegerTypeNames.testref new file mode 100644 index 0000000000..bb41437be6 --- /dev/null +++ b/cpp/misra/test/rules/RULE-6-9-2/AvoidStandardIntegerTypeNames.testref @@ -0,0 +1 @@ +cpp/common/test/rules/variablewidthintegertypesused/VariableWidthIntegerTypesUsed.ql \ 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..313b513315 --- /dev/null +++ b/rule_packages/cpp/BannedAPIs.json @@ -0,0 +1,205 @@ +{ + "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" + }, + "RULE-6-9-2": { + "properties": { + "enforcement": "decidable", + "obligation": "advisory" + }, + "queries": [ + { + "description": "Using standard signed and unsigned integer type names instead of specified width types makes storage requirements unclear and implementation-dependent.", + "kind": "problem", + "name": "The names of the standard signed integer types and standard unsigned integer types should not be", + "precision": "very-high", + "severity": "error", + "short_name": "AvoidStandardIntegerTypeNames", + "shared_implementation_short_name": "VariableWidthIntegerTypesUsed", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "The names of the standard signed integer types and standard unsigned integer types should not be used" + } + } +} \ No newline at end of file diff --git a/rule_packages/cpp/Declarations.json b/rule_packages/cpp/Declarations.json index a5b8ebeec3..61d286026a 100644 --- a/rule_packages/cpp/Declarations.json +++ b/rule_packages/cpp/Declarations.json @@ -92,8 +92,9 @@ "maintainability" ], "implementation_scope": { - "description": "This implementation excludes the plain char type from consideration." - } + "description": "This implementation excludes the plain char type. It also excludes the use of standard integer types in the definition of main functions, and the use of an integer parameter in the declaration of postfix operators." + }, + "shared_implementation_short_name": "VariableWidthIntegerTypesUsed" }, { "description": "The basic numerical type char is not supposed to be used. The specific-length types from header need be used instead.",