diff --git a/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql b/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql index 005b7c6cf5..6fdde80119 100644 --- a/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql +++ b/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql @@ -14,6 +14,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.misra.EssentialTypes +import codingstandards.cpp.Bitwise /** * Holds if the operator `operator` has an operand `child` that is of an inappropriate essential type @@ -177,7 +178,7 @@ predicate isInappropriateEssentialType( child = [ operator.(BinaryBitwiseOperation).getAnOperand(), - operator.(AssignBitwiseOperation).getAnOperand() + operator.(Bitwise::AssignBitwiseOperation).getAnOperand() ] and not operator instanceof LShiftExpr and not operator instanceof RShiftExpr and diff --git a/c/misra/test/rules/RULE-10-1/test.c b/c/misra/test/rules/RULE-10-1/test.c index 8945890d4c..19b7d2e3e8 100644 --- a/c/misra/test/rules/RULE-10-1/test.c +++ b/c/misra/test/rules/RULE-10-1/test.c @@ -492,4 +492,6 @@ void pointerType() { b || b; // COMPLIANT p || b; // NON_COMPLIANT b || p; // NON_COMPLIANT + p += 1; // COMPLIANT + p -= 1; // COMPLIANT } diff --git a/change_notes/2023-10-04-m5-0-20-exclude-pointer-bitwise.md b/change_notes/2023-10-04-m5-0-20-exclude-pointer-bitwise.md new file mode 100644 index 0000000000..dc8d47f064 --- /dev/null +++ b/change_notes/2023-10-04-m5-0-20-exclude-pointer-bitwise.md @@ -0,0 +1 @@ + * `M5-0-20`, `M5-0-21`, `RULE-10-1` - exclude pointer assignment operators as bitwise operators. \ No newline at end of file diff --git a/change_notes/2023-11-07-use-misra-underlying-type.md b/change_notes/2023-11-07-use-misra-underlying-type.md new file mode 100644 index 0000000000..e322e8c2dd --- /dev/null +++ b/change_notes/2023-11-07-use-misra-underlying-type.md @@ -0,0 +1,2 @@ +- `M5-0-20` - `BitwiseOperatorOperandsHaveDifferentUnderlyingType.ql`: + - Use the Misra definition of underlying type. diff --git a/cpp/autosar/src/rules/M5-0-20/BitwiseOperatorOperandsHaveDifferentUnderlyingType.ql b/cpp/autosar/src/rules/M5-0-20/BitwiseOperatorOperandsHaveDifferentUnderlyingType.ql index e1a8f568e8..9e85a15e50 100644 --- a/cpp/autosar/src/rules/M5-0-20/BitwiseOperatorOperandsHaveDifferentUnderlyingType.ql +++ b/cpp/autosar/src/rules/M5-0-20/BitwiseOperatorOperandsHaveDifferentUnderlyingType.ql @@ -16,19 +16,30 @@ import cpp import codingstandards.cpp.autosar +import codingstandards.cpp.Bitwise +import codingstandards.cpp.Conversion predicate isBinaryBitwiseOperation(Operation o, VariableAccess l, VariableAccess r) { exists(BinaryBitwiseOperation bbo | bbo = o | l = bbo.getLeftOperand() and r = bbo.getRightOperand() ) or - exists(AssignBitwiseOperation abo | abo = o | l = abo.getLValue() and r = abo.getRValue()) + exists(Bitwise::AssignBitwiseOperation abo | abo = o | + l = abo.getLValue() and + r = abo.getRValue() + ) } -from Operation o, Variable left, Variable right +from + Operation o, VariableAccess left, VariableAccess right, Type leftUnderlyingType, + Type rightUnderlyingType where not isExcluded(o, ExpressionsPackage::bitwiseOperatorOperandsHaveDifferentUnderlyingTypeQuery()) and not o.isFromUninstantiatedTemplate(_) and - isBinaryBitwiseOperation(o, left.getAnAccess(), right.getAnAccess()) and - left.getUnderlyingType() != right.getUnderlyingType() -select o, "Operands of the '" + o.getOperator() + "' operation have different underlying types." + isBinaryBitwiseOperation(o, left, right) and + leftUnderlyingType = MisraConversion::getUnderlyingType(left) and + rightUnderlyingType = MisraConversion::getUnderlyingType(right) and + leftUnderlyingType != rightUnderlyingType +select o, + "Operands of the '" + o.getOperator() + "' operation have different underlying types '" + + leftUnderlyingType.getName() + "' and '" + rightUnderlyingType.getName() + "'." diff --git a/cpp/autosar/src/rules/M5-0-21/BitwiseOperatorAppliedToSignedTypes.ql b/cpp/autosar/src/rules/M5-0-21/BitwiseOperatorAppliedToSignedTypes.ql index 02bb5314cd..d000155189 100644 --- a/cpp/autosar/src/rules/M5-0-21/BitwiseOperatorAppliedToSignedTypes.ql +++ b/cpp/autosar/src/rules/M5-0-21/BitwiseOperatorAppliedToSignedTypes.ql @@ -17,6 +17,7 @@ import cpp import codingstandards.cpp.autosar +import codingstandards.cpp.Bitwise from Operation o, VariableAccess va where @@ -24,7 +25,7 @@ where ( o instanceof UnaryBitwiseOperation or o instanceof BinaryBitwiseOperation or - o instanceof AssignBitwiseOperation + o instanceof Bitwise::AssignBitwiseOperation ) and o.getAnOperand() = va and va.getTarget().getUnderlyingType().(IntegralType).isSigned() diff --git a/cpp/autosar/src/rules/M5-8-1/RightBitShiftOperandIsNegativeOrTooWide.ql b/cpp/autosar/src/rules/M5-8-1/RightBitShiftOperandIsNegativeOrTooWide.ql index b94d76fd94..38da7115f3 100644 --- a/cpp/autosar/src/rules/M5-8-1/RightBitShiftOperandIsNegativeOrTooWide.ql +++ b/cpp/autosar/src/rules/M5-8-1/RightBitShiftOperandIsNegativeOrTooWide.ql @@ -17,6 +17,7 @@ import cpp import codingstandards.cpp.autosar +import codingstandards.cpp.Bitwise class ShiftOperation extends Operation { Expr leftOperand; @@ -33,7 +34,7 @@ class ShiftOperation extends Operation { rightOperand = o.getRightOperand() ) or - exists(AssignBitwiseOperation o | this = o | + exists(Bitwise::AssignBitwiseOperation o | this = o | ( o instanceof AssignLShiftExpr or diff --git a/cpp/autosar/test/rules/M5-0-20/BitwiseOperatorOperandsHaveDifferentUnderlyingType.expected b/cpp/autosar/test/rules/M5-0-20/BitwiseOperatorOperandsHaveDifferentUnderlyingType.expected index ac31001f57..806c82599d 100644 --- a/cpp/autosar/test/rules/M5-0-20/BitwiseOperatorOperandsHaveDifferentUnderlyingType.expected +++ b/cpp/autosar/test/rules/M5-0-20/BitwiseOperatorOperandsHaveDifferentUnderlyingType.expected @@ -1,21 +1,21 @@ -| test.cpp:18:3:18:6 | ... & ... | Operands of the '&' operation have different underlying types. | -| test.cpp:19:3:19:7 | ... \| ... | Operands of the '\|' operation have different underlying types. | -| test.cpp:20:3:20:7 | ... ^ ... | Operands of the '^' operation have different underlying types. | -| test.cpp:21:3:21:8 | ... << ... | Operands of the '<<' operation have different underlying types. | -| test.cpp:22:3:22:8 | ... >> ... | Operands of the '>>' operation have different underlying types. | -| test.cpp:23:3:23:8 | ... &= ... | Operands of the '&=' operation have different underlying types. | -| test.cpp:24:3:24:8 | ... \|= ... | Operands of the '\|=' operation have different underlying types. | -| test.cpp:25:3:25:8 | ... ^= ... | Operands of the '^=' operation have different underlying types. | -| test.cpp:26:3:26:9 | ... <<= ... | Operands of the '<<=' operation have different underlying types. | -| test.cpp:27:3:27:9 | ... >>= ... | Operands of the '>>=' operation have different underlying types. | -| test.cpp:45:3:45:6 | ... & ... | Operands of the '&' operation have different underlying types. | -| test.cpp:46:3:46:7 | ... \| ... | Operands of the '\|' operation have different underlying types. | -| test.cpp:47:3:47:7 | ... ^ ... | Operands of the '^' operation have different underlying types. | -| test.cpp:48:3:48:8 | ... << ... | Operands of the '<<' operation have different underlying types. | -| test.cpp:49:3:49:8 | ... >> ... | Operands of the '>>' operation have different underlying types. | -| test.cpp:50:3:50:8 | ... &= ... | Operands of the '&=' operation have different underlying types. | -| test.cpp:51:3:51:8 | ... \|= ... | Operands of the '\|=' operation have different underlying types. | -| test.cpp:52:3:52:8 | ... ^= ... | Operands of the '^=' operation have different underlying types. | -| test.cpp:53:3:53:9 | ... <<= ... | Operands of the '<<=' operation have different underlying types. | -| test.cpp:54:3:54:9 | ... >>= ... | Operands of the '>>=' operation have different underlying types. | -| test.cpp:67:3:67:14 | ... << ... | Operands of the '<<' operation have different underlying types. | +| test.cpp:18:3:18:6 | ... & ... | Operands of the '&' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:19:3:19:7 | ... \| ... | Operands of the '\|' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:20:3:20:7 | ... ^ ... | Operands of the '^' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:21:3:21:8 | ... << ... | Operands of the '<<' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:22:3:22:8 | ... >> ... | Operands of the '>>' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:23:3:23:8 | ... &= ... | Operands of the '&=' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:24:3:24:8 | ... \|= ... | Operands of the '\|=' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:25:3:25:8 | ... ^= ... | Operands of the '^=' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:26:3:26:9 | ... <<= ... | Operands of the '<<=' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:27:3:27:9 | ... >>= ... | Operands of the '>>=' operation have different underlying types 'unsigned int' and 'unsigned short'. | +| test.cpp:45:3:45:6 | ... & ... | Operands of the '&' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:46:3:46:7 | ... \| ... | Operands of the '\|' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:47:3:47:7 | ... ^ ... | Operands of the '^' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:48:3:48:8 | ... << ... | Operands of the '<<' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:49:3:49:8 | ... >> ... | Operands of the '>>' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:50:3:50:8 | ... &= ... | Operands of the '&=' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:51:3:51:8 | ... \|= ... | Operands of the '\|=' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:52:3:52:8 | ... ^= ... | Operands of the '^=' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:53:3:53:9 | ... <<= ... | Operands of the '<<=' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:54:3:54:9 | ... >>= ... | Operands of the '>>=' operation have different underlying types 'unsigned char' and 'unsigned short'. | +| test.cpp:67:3:67:14 | ... << ... | Operands of the '<<' operation have different underlying types 'int &' and 'char &'. | diff --git a/cpp/autosar/test/rules/M5-0-20/test.cpp b/cpp/autosar/test/rules/M5-0-20/test.cpp index 925a5ec6b8..2db9252445 100644 --- a/cpp/autosar/test/rules/M5-0-20/test.cpp +++ b/cpp/autosar/test/rules/M5-0-20/test.cpp @@ -71,3 +71,8 @@ void test463_2_instantiations() { char shift2 = 2; test463_2(val, shift2); } + +void test_add(char *val) { + int add = 2; + val += add; // COMPLIANT +} \ No newline at end of file diff --git a/cpp/autosar/test/rules/M5-0-21/test.cpp b/cpp/autosar/test/rules/M5-0-21/test.cpp index eb6c88c8be..0dbedd9f1f 100644 --- a/cpp/autosar/test/rules/M5-0-21/test.cpp +++ b/cpp/autosar/test/rules/M5-0-21/test.cpp @@ -45,4 +45,8 @@ void test() { u ^= u; // COMPLIANT u | 0; // COMPLIANT u |= 0; // COMPLIANT + + int *p = 0; + p += 1; // COMPLIANT + p -= 1; // COMPLIANT } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Bitwise.qll b/cpp/common/src/codingstandards/cpp/Bitwise.qll new file mode 100644 index 0000000000..0e19cae29d --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/Bitwise.qll @@ -0,0 +1,20 @@ +/** + * A library for addressing issues in bitwise operator modelling in our database schema. + */ + +private import cpp as cpp + +module Bitwise { + /** + * A binary bitwise assign operation, excluding += and -= on pointers, which seem to be erroneously + * included. + */ + class AssignBitwiseOperation extends cpp::AssignBitwiseOperation { + AssignBitwiseOperation() { + // exclude += and -= on pointers, which seem to be erroneously included + // in the database schema + not this instanceof cpp::AssignPointerAddExpr and + not this instanceof cpp::AssignPointerSubExpr + } + } +}