diff --git a/c/misra/src/codingstandards/c/misra/EssentialTypes.qll b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll new file mode 100644 index 0000000000..697a24513f --- /dev/null +++ b/c/misra/src/codingstandards/c/misra/EssentialTypes.qll @@ -0,0 +1,376 @@ +/** + * A module for identifying essential types as defined by MISRA C 2012. + */ + +import codingstandards.c.misra +import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils +import MisraExpressions + +newtype TEssentialTypeCategory = + EssentiallyBooleanType() or + EssentiallyCharacterType() or + EssentiallyEnumType() or + EssentiallySignedType() or + EssentiallyUnsignedType() or + EssentiallyFloatingType() + +/** An essential type category, as specified by Appendix D.1. */ +class EssentialTypeCategory extends TEssentialTypeCategory { + string toString() { + this = EssentiallyBooleanType() and result = "essentially Boolean type" + or + this = EssentiallyCharacterType() and result = "essentially Character type" + or + this = EssentiallyEnumType() and result = "essentially Enum Type" + or + this = EssentiallySignedType() and result = "essentially Signed type" + or + this = EssentiallyUnsignedType() and result = "essentially Unsigned type" + or + this = EssentiallyFloatingType() and result = "essentially Floating type" + } +} + +/** + * Gets the unsigned type of lowest rank that can represent the value of the given expression, + * assuming that the expression is essentially unsigned. + */ +private IntegralType utlr(Expr const) { + getEssentialTypeCategory(const.getType()) = EssentiallyUnsignedType() and + getEssentialTypeCategory(result) = EssentiallyUnsignedType() and + exists(float c | c = const.getValue().toFloat() | + // As with range analysis, we assume two's complement representation + typeLowerBound(result) <= c and + typeUpperBound(result) >= c and + forall(IntegralType it | + getEssentialTypeCategory(it) = EssentiallyUnsignedType() and + typeLowerBound(it) <= c and + typeUpperBound(it) >= c + | + result.getSize() <= it.getSize() + ) + ) +} + +/** + * Gets the signed type of lowest rank that can represent the value of the given expression, + * assuming that the expression is essentially signed. + */ +private IntegralType stlr(Expr const) { + getEssentialTypeCategory(const.getType()) = EssentiallySignedType() and + getEssentialTypeCategory(result) = EssentiallySignedType() and + exists(float c | c = const.getValue().toFloat() | + // As with range analysis, we assume two's complement representation + typeLowerBound(result) <= c and + typeUpperBound(result) >= c and + forall(IntegralType it | + getEssentialTypeCategory(it) = EssentiallySignedType() and + typeLowerBound(it) <= c and + typeUpperBound(it) >= c + | + result.getSize() <= it.getSize() + ) + ) +} + +/** + * Define the essential type category for an essentialType or a typedef of an essentialType. + */ +EssentialTypeCategory getEssentialTypeCategory(Type type) { + exists(Type essentialType | + if type instanceof MisraBoolType + then essentialType = type + else + // If not a bool type, resolve the typedefs to determine the actual type + essentialType = type.getUnspecifiedType() + | + result = EssentiallyBooleanType() and essentialType instanceof MisraBoolType + or + result = EssentiallyCharacterType() and essentialType instanceof PlainCharType + or + result = EssentiallySignedType() and + essentialType.(IntegralType).isSigned() and + not essentialType instanceof PlainCharType + or + result = EssentiallyUnsignedType() and + essentialType.(IntegralType).isUnsigned() and + not essentialType instanceof PlainCharType + or + result = EssentiallyEnumType() and + essentialType instanceof Enum and + not essentialType instanceof MisraBoolType + or + result = EssentiallyFloatingType() and + essentialType instanceof FloatingPointType + ) +} + +/** + * Gets the essential type of the given expression `e`, considering any explicit conversions. + */ +Type getEssentialType(Expr e) { + if e.hasExplicitConversion() + then + if e.getConversion() instanceof ParenthesisExpr + then + if e.getConversion().(ParenthesisExpr).hasExplicitConversion() + then result = e.getConversion().(ParenthesisExpr).getConversion().getType() + else result = e.getConversion().(ParenthesisExpr).getExpr().(EssentialExpr).getEssentialType() + else result = e.getConversion().getType() + else result = e.(EssentialExpr).getEssentialType() +} + +Type getEssentialTypeBeforeConversions(Expr e) { result = e.(EssentialExpr).getEssentialType() } + +class EssentialExpr extends Expr { + Type getEssentialType() { result = this.getType() } + + Type getStandardType() { result = this.getType() } +} + +class EssentialCommaExpr extends EssentialExpr, CommaExpr { + override Type getEssentialType() { result = getEssentialType(getRightOperand()) } +} + +class EssentialRelationalOperationExpr extends EssentialExpr, RelationalOperation { + override Type getEssentialType() { result instanceof BoolType } +} + +class EssentialBinaryLogicalOperationExpr extends EssentialExpr, BinaryLogicalOperation { + override Type getEssentialType() { result instanceof BoolType } +} + +class EssentialEqualityOperationExpr extends EssentialExpr, EqualityOperation { + override Type getEssentialType() { result instanceof BoolType } +} + +class EssentialBinaryBitwiseOperationExpr extends EssentialExpr, BinaryBitwiseOperation { + EssentialBinaryBitwiseOperationExpr() { + this instanceof LShiftExpr or + this instanceof RShiftExpr + } + + override Type getEssentialType() { + exists(Type operandEssentialType, EssentialTypeCategory operandEssentialTypeCategory | + operandEssentialType = getEssentialType(getLeftOperand()) and + operandEssentialTypeCategory = getEssentialTypeCategory(operandEssentialType) + | + if operandEssentialTypeCategory instanceof EssentiallyUnsignedType + then + if exists(this.getValue()) + then result = utlr(this) // If constant and essentially unsigned us the utlr + else result = operandEssentialType + else result = this.getStandardType() + ) + } +} + +class EssentialBitwiseComplementExpr extends EssentialExpr, ComplementExpr { + override Type getEssentialType() { + exists(Type operandEssentialType, EssentialTypeCategory operandEssentialTypeCategory | + operandEssentialType = getEssentialType(getOperand()) and + operandEssentialTypeCategory = getEssentialTypeCategory(operandEssentialType) + | + if operandEssentialTypeCategory instanceof EssentiallyUnsignedType + then + if exists(this.getValue()) + then result = utlr(this) // If constant and essentially unsigned us the utlr + else result = operandEssentialType + else result = this.getStandardType() + ) + } +} + +class EssentialUnaryPlusExpr extends EssentialExpr, UnaryPlusExpr { + override Type getEssentialType() { + exists(Type operandEssentialType, EssentialTypeCategory operandEssentialTypeCategory | + operandEssentialType = getEssentialType(getOperand()) and + operandEssentialTypeCategory = getEssentialTypeCategory(operandEssentialType) + | + if + operandEssentialTypeCategory = + [EssentiallyUnsignedType().(TEssentialTypeCategory), EssentiallySignedType()] + then result = operandEssentialType + else result = getStandardType() + ) + } +} + +class EssentialUnaryMinusExpr extends EssentialExpr, UnaryMinusExpr { + override Type getEssentialType() { + exists(Type operandEssentialType, EssentialTypeCategory operandEssentialTypeCategory | + operandEssentialType = getEssentialType(getOperand()) and + operandEssentialTypeCategory = getEssentialTypeCategory(operandEssentialType) + | + if operandEssentialTypeCategory = EssentiallySignedType() + then if exists(this.getValue()) then result = stlr(this) else result = operandEssentialType + else result = getStandardType() + ) + } +} + +class EssentialConditionalExpr extends EssentialExpr, ConditionalExpr { + override Type getEssentialType() { + exists(Type thenEssentialType, Type elseEssentialType | + thenEssentialType = getEssentialType(getThen()) and + elseEssentialType = getEssentialType(getElse()) + | + if thenEssentialType = elseEssentialType + then result = thenEssentialType + else + if + getEssentialTypeCategory(thenEssentialType) = EssentiallySignedType() and + getEssentialTypeCategory(elseEssentialType) = EssentiallySignedType() + then + if thenEssentialType.getSize() > elseEssentialType.getSize() + then result = thenEssentialType + else result = elseEssentialType + else + if + getEssentialTypeCategory(thenEssentialType) = EssentiallyUnsignedType() and + getEssentialTypeCategory(elseEssentialType) = EssentiallyUnsignedType() + then + if thenEssentialType.getSize() > elseEssentialType.getSize() + then result = thenEssentialType + else result = elseEssentialType + else result = this.getStandardType() + ) + } +} + +class EssentialBinaryArithmeticExpr extends EssentialExpr, BinaryArithmeticOperation { + EssentialBinaryArithmeticExpr() { + // GNU C extension has min/max which we can ignore + not this instanceof MinExpr and + not this instanceof MaxExpr + } + + override Type getEssentialType() { + exists( + Type leftEssentialType, Type rightEssentialType, + EssentialTypeCategory leftEssentialTypeCategory, + EssentialTypeCategory rightEssentialTypeCategory + | + leftEssentialType = getEssentialType(getLeftOperand()) and + rightEssentialType = getEssentialType(getRightOperand()) and + leftEssentialTypeCategory = getEssentialTypeCategory(leftEssentialType) and + rightEssentialTypeCategory = getEssentialTypeCategory(rightEssentialType) + | + if + leftEssentialTypeCategory = EssentiallySignedType() and + rightEssentialTypeCategory = EssentiallySignedType() + then + if exists(getValue()) + then result = stlr(this) + else ( + if leftEssentialType.getSize() > rightEssentialType.getSize() + then result = leftEssentialType + else result = rightEssentialType + ) + else + if + leftEssentialTypeCategory = EssentiallyUnsignedType() and + rightEssentialTypeCategory = EssentiallyUnsignedType() + then + if exists(getValue()) + then result = utlr(this) + else ( + if leftEssentialType.getSize() > rightEssentialType.getSize() + then result = leftEssentialType + else result = rightEssentialType + ) + else + if + this instanceof AddExpr and + ( + leftEssentialTypeCategory = EssentiallyCharacterType() + or + rightEssentialTypeCategory = EssentiallyCharacterType() + ) and + ( + leftEssentialTypeCategory = + [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + or + rightEssentialTypeCategory = + [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + ) + or + this instanceof SubExpr and + leftEssentialTypeCategory = EssentiallyCharacterType() and + rightEssentialTypeCategory = + [EssentiallySignedType(), EssentiallyUnsignedType().(TEssentialTypeCategory)] + then result instanceof PlainCharType + else result = this.getStandardType() + ) + } +} + +class EssentialEnumConstantAccess extends EssentialExpr, EnumConstantAccess { + override Type getEssentialType() { result = getTarget().getDeclaringEnum() } +} + +class EssentialLiteral extends EssentialExpr, Literal { + override Type getEssentialType() { + if this instanceof BooleanLiteral + then result instanceof MisraBoolType + else ( + if this.(CharLiteral).getCharacter().length() = 1 + then result instanceof PlainCharType + else ( + getStandardType().(IntegralType).isSigned() and + result = stlr(this) + or + not getStandardType().(IntegralType).isSigned() and + result = utlr(this) + ) + ) + } +} + +/** + * Holds if `rValue` is assigned to an object of type `lValueEssentialType`. + * + * Assignment is according to "Assignment" in Appendix J of MISRA C 2012, with the inclusion of a + * special case for switch statements as specified for Rule 10.3 and Rule 10.6. + */ +predicate isAssignmentToEssentialType(Type lValueEssentialType, Expr rValue) { + // Special case for Rule 10.3/ Rule 10.6. + exists(SwitchCase sc | + lValueEssentialType = sc.getSwitchStmt().getControllingExpr().getType() and + rValue = sc.getExpr() + ) + or + exists(Assignment a | + lValueEssentialType = a.getLValue().getType() and + rValue = a.getRValue() + ) + or + exists(FunctionCall fc, int i | + lValueEssentialType = fc.getTarget().getParameter(i).getType() and + rValue = fc.getArgument(i) + ) + or + exists(Function f, ReturnStmt rs | + lValueEssentialType = f.getType() and + rs.getEnclosingFunction() = f and + rValue = rs.getExpr() + ) + or + // Initializing a non-aggregate type + exists(Initializer i | + lValueEssentialType = i.getDeclaration().(Variable).getType() and + rValue = i.getExpr() + ) + or + // Initializing an array + exists(ArrayAggregateLiteral aal | + lValueEssentialType = aal.getElementType() and + rValue = aal.getElementExpr(_) + ) + or + // Initializing a struct or union + exists(ClassAggregateLiteral cal, Field field | + lValueEssentialType = field.getType() and + rValue = cal.getFieldExpr(field) + ) +} diff --git a/c/misra/src/codingstandards/c/misra/MisraExpressions.qll b/c/misra/src/codingstandards/c/misra/MisraExpressions.qll new file mode 100644 index 0000000000..b5f03838cc --- /dev/null +++ b/c/misra/src/codingstandards/c/misra/MisraExpressions.qll @@ -0,0 +1,106 @@ +/** + * A module for representing expressions and related types defined in the MISRA C 2012 standard. + */ + +import codingstandards.c.misra + +/** + * A `bool` type, either `stdbool.h` or a hand-coded bool type acceptable to MISRA C 2012. + */ +class MisraBoolType extends Type { + MisraBoolType() { + this instanceof BoolType + or + exists(Enum e | this = e | + count(e.getAnEnumConstant()) = 2 and + e.getEnumConstant(0).getName().toLowerCase() = ["false", "f"] and + e.getEnumConstant(1).getName().toLowerCase() = ["true", "t"] + ) + or + exists(TypedefType t | this = t | t.getName().toLowerCase() = ["bool", "boolean"]) + } +} + +/** + * A boolean literal as defined by the C standard and acceptable to MISRA C 2012. + */ +class BooleanLiteral extends Literal { + BooleanLiteral() { + exists(MacroInvocation mi, int value, string macroName | + macroName = mi.getMacroName() and mi.getExpr() = this and value = this.getValue().toInt() + | + macroName = "false" and value = 0 + or + macroName = "true" and value = 1 + ) + } +} + +/** + * A composite operator as defined in MISRA C:2012 8.10.3. + */ +class CompositeOperator extends Expr { + CompositeOperator() { + // + - * / % + - + this instanceof BinaryArithmeticOperation and + not this instanceof MaxExpr and + not this instanceof MinExpr + or + // << >> & ^ | + this instanceof BinaryBitwiseOperation + or + // ~ + this instanceof ComplementExpr + or + exists(ConditionalExpr ce | ce = this | + ce.getElse() instanceof CompositeExpression or ce.getThen() instanceof CompositeExpression + ) + } +} + +/** + * A composite expression as defined in MISRA C:2012 8.10.3. + */ +class CompositeExpression extends Expr { + CompositeExpression() { + this instanceof CompositeOperator and + // A non-constant expression that is the result of a composite operator + not exists(this.getValue()) + } +} + +/** + * An operator on which the usual arithmetic conversions apply to the operands, as defined in MISRA + * C:2012 6.3.1.8. + */ +class OperationWithUsualArithmeticConversions extends Expr { + OperationWithUsualArithmeticConversions() { + this instanceof BinaryOperation and + not this instanceof LShiftExpr and + not this instanceof RShiftExpr and + not this instanceof LogicalAndExpr and + not this instanceof LogicalOrExpr + or + this instanceof AssignArithmeticOperation + } + + Expr getLeftOperand() { + result = this.(BinaryOperation).getLeftOperand() + or + result = this.(AssignArithmeticOperation).getLValue() + } + + Expr getRightOperand() { + result = this.(BinaryOperation).getRightOperand() + or + result = this.(AssignArithmeticOperation).getRValue() + } + + Expr getAnOperand() { result = this.getLeftOperand() or result = this.getRightOperand() } + + string getOperator() { + result = this.(BinaryOperation).getOperator() + or + result = this.(AssignArithmeticOperation).getOperator() + } +} diff --git a/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql b/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql new file mode 100644 index 0000000000..005b7c6cf5 --- /dev/null +++ b/c/misra/src/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql @@ -0,0 +1,253 @@ +/** + * @id c/misra/operands-of-an-inappropriate-essential-type + * @name RULE-10-1: Operands shall not be of an inappropriate essential type + * @description Using an inappropriate essential type operand may lead to confusing or unexpected + * behavior when the operand is converted. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-10-1 + * maintainability + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes + +/** + * Holds if the operator `operator` has an operand `child` that is of an inappropriate essential type + * according to MISRA C 2012 Rule 10.1. + */ +predicate isInappropriateEssentialType( + Expr operator, Expr child, EssentialTypeCategory etc, int rationaleId +) { + etc = getEssentialTypeCategory(getEssentialType(child)) and + ( + child = operator.(ArrayExpr).getArrayOffset() and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyCharacterType() and + rationaleId = 4 + or + etc = EssentiallyFloatingType() and + rationaleId = 1 + ) + or + child = operator.(UnaryPlusExpr).getOperand() and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyCharacterType() and + rationaleId = 4 + or + etc = EssentiallyEnumType() and + rationaleId = 5 + ) + or + child = operator.(UnaryMinusExpr).getOperand() and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyCharacterType() and + rationaleId = 4 + or + etc = EssentiallyEnumType() and + rationaleId = 5 + or + etc = EssentiallyUnsignedType() and + rationaleId = 8 + ) + or + // The table only talks about + and -, but below it clarifies ++ and -- are also considered to + // be equivalent. + child = + [ + operator.(AddExpr).getAnOperand(), operator.(SubExpr).getAnOperand(), + operator.(IncrementOperation).getAnOperand(), operator.(DecrementOperation).getAnOperand(), + operator.(AssignAddExpr).getAnOperand(), operator.(AssignSubExpr).getAnOperand() + ] and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyEnumType() and + rationaleId = 5 + ) + or + child = + [ + operator.(DivExpr).getAnOperand(), operator.(MulExpr).getAnOperand(), + operator.(AssignDivExpr).getAnOperand(), operator.(AssignMulExpr).getAnOperand() + ] and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyCharacterType() and + rationaleId = 4 + or + etc = EssentiallyEnumType() and + rationaleId = 5 + ) + or + child = [operator.(RemExpr).getAnOperand(), operator.(AssignRemExpr).getAnOperand()] and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyCharacterType() and + rationaleId = 4 + or + etc = EssentiallyEnumType() and + rationaleId = 5 + or + etc = EssentiallyFloatingType() and + rationaleId = 1 + ) + or + child = operator.(RelationalOperation).getAnOperand() and + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + child = [operator.(NotExpr).getAnOperand(), operator.(BinaryLogicalOperation).getAnOperand()] and + rationaleId = 2 and + ( + etc = EssentiallyCharacterType() + or + etc = EssentiallyEnumType() + or + etc = EssentiallySignedType() + or + etc = EssentiallyUnsignedType() + or + etc = EssentiallyFloatingType() + ) + or + child = + [ + operator.(LShiftExpr).getLeftOperand(), operator.(RShiftExpr).getLeftOperand(), + operator.(AssignLShiftExpr).getLValue(), operator.(AssignRShiftExpr).getLValue() + ] and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyCharacterType() and + rationaleId = 4 + or + etc = EssentiallyEnumType() and + rationaleId = 6 // 5 also applies, but 6 is sufficient explanation + or + etc = EssentiallySignedType() and + rationaleId = 6 + or + etc = EssentiallyFloatingType() and + rationaleId = 1 + ) + or + child = + [ + operator.(LShiftExpr).getRightOperand(), operator.(RShiftExpr).getRightOperand(), + operator.(AssignLShiftExpr).getRValue(), operator.(AssignRShiftExpr).getRValue() + ] and + // Integer constant non negative essentially signed types are allowed by exception + not (child.getValue().toInt() >= 0 and etc = EssentiallySignedType()) and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyCharacterType() and + rationaleId = 4 + or + etc = EssentiallyEnumType() and + rationaleId = 7 + or + etc = EssentiallySignedType() and + rationaleId = 7 + or + etc = EssentiallyFloatingType() and + rationaleId = 1 + ) + or + child = + [ + operator.(BinaryBitwiseOperation).getAnOperand(), + operator.(AssignBitwiseOperation).getAnOperand() + ] and + not operator instanceof LShiftExpr and + not operator instanceof RShiftExpr and + not operator instanceof AssignLShiftExpr and + not operator instanceof AssignRShiftExpr and + ( + etc = EssentiallyBooleanType() and + rationaleId = 3 + or + etc = EssentiallyCharacterType() and + rationaleId = 4 + or + etc = EssentiallyEnumType() and + rationaleId = 6 + or + etc = EssentiallySignedType() and + rationaleId = 6 + or + etc = EssentiallyFloatingType() and + rationaleId = 1 + ) + or + child = operator.(ConditionalExpr).getCondition() and + ( + etc = EssentiallyCharacterType() and + rationaleId = 2 + or + etc = EssentiallyEnumType() and + rationaleId = 2 + or + etc = EssentiallySignedType() and + rationaleId = 2 + or + etc = EssentiallyUnsignedType() and + rationaleId = 2 + or + etc = EssentiallyFloatingType() and + rationaleId = 2 + ) + ) +} + +string getRationaleMessage(int rationaleId, EssentialTypeCategory etc) { + rationaleId = 1 and + result = "Constraint violation from using an operand of essentially Floating type." + or + rationaleId = 2 and result = "Operand of " + etc + " type interpreted as a Boolean value." + or + rationaleId = 3 and result = "Operand of essentially Boolean type interpreted as a numeric value." + or + rationaleId = 4 and + result = "Operand of essentially Charater type interpreted as a numeric value." + or + rationaleId = 5 and + result = + "Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type." + or + rationaleId = 6 and + result = "Bitwise operator applied to operand of " + etc + " and not essentially unsigned." + or + rationaleId = 7 and + result = "Right hand operatand of shift operator is " + etc + " and not not essentially unsigned." + or + rationaleId = 8 and + result = + "Operand of essentially Unsigned type will be converted to a signed type with the signedness dependent on the implemented size of int." +} + +from Expr operator, Expr child, int rationaleId, EssentialTypeCategory etc +where + not isExcluded(operator, EssentialTypesPackage::operandsOfAnInappropriateEssentialTypeQuery()) and + isInappropriateEssentialType(operator, child, etc, rationaleId) +select operator, getRationaleMessage(rationaleId, etc) diff --git a/c/misra/src/rules/RULE-10-1/PointerTypeOnLogicalOperator.ql b/c/misra/src/rules/RULE-10-1/PointerTypeOnLogicalOperator.ql new file mode 100644 index 0000000000..21bfdcb2be --- /dev/null +++ b/c/misra/src/rules/RULE-10-1/PointerTypeOnLogicalOperator.ql @@ -0,0 +1,26 @@ +/** + * @id c/misra/pointer-type-on-logical-operator + * @name RULE-10-1: Logical operators should not be used with pointer types + * @description Using pointer types with logical operators should be avoid because it can cause + * confusing behavior. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-10-1 + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra + +from Expr logicalOperator, Expr operand +where + not isExcluded(operand, EssentialTypesPackage::pointerTypeOnLogicalOperatorQuery()) and + ( + operand = logicalOperator.(BinaryLogicalOperation).getAnOperand() + or + operand = logicalOperator.(NotExpr).getOperand() + ) and + operand.getType() instanceof PointerType +select operand, "Logical operators should not be used with pointer types." diff --git a/c/misra/src/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.ql b/c/misra/src/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.ql new file mode 100644 index 0000000000..ad0c630e23 --- /dev/null +++ b/c/misra/src/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.ql @@ -0,0 +1,42 @@ +/** + * @id c/misra/addition-subtraction-on-essentially-char-type + * @name RULE-10-2: Inappropriate use of essentially character type operands in addition and subtraction operations + * @description Expressions of essentially character type shall not be used inappropriately in + * addition and subtraction operations. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-10-2 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes + +from BinaryArithmeticOperation addOrSub +where + not isExcluded(addOrSub, EssentialTypesPackage::additionSubtractionOnEssentiallyCharTypeQuery()) and + addOrSub.getOperator() = ["+", "-"] and + // At least one operand is essentially character type + ( + getEssentialTypeCategory(getEssentialType(addOrSub.getLeftOperand())) = + EssentiallyCharacterType() or + getEssentialTypeCategory(getEssentialType(addOrSub.getRightOperand())) = + EssentiallyCharacterType() + ) and + not ( + // But the overall essential type is not essentially character type + getEssentialTypeCategory(getEssentialType(addOrSub)) = EssentiallyCharacterType() + or + // Or this is a subtration of one character with another, which is permitted, but produces an integral type + getEssentialTypeCategory(getEssentialType(addOrSub.getLeftOperand())) = + EssentiallyCharacterType() and + getEssentialTypeCategory(getEssentialType(addOrSub.getRightOperand())) = + EssentiallyCharacterType() and + addOrSub instanceof SubExpr + ) +select addOrSub, + "Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations" diff --git a/c/misra/src/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.ql b/c/misra/src/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.ql new file mode 100644 index 0000000000..353f6a9c8d --- /dev/null +++ b/c/misra/src/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.ql @@ -0,0 +1,51 @@ +/** + * @id c/misra/assignment-of-incompatible-essential-type + * @name RULE-10-3: Do not assign to an object with a different essential type category or narrower essential type + * @description The value of an expression shall not be assigned to an object with a narrower + * essential type or of a different essential type category. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-10-3 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import codingstandards.c.misra.MisraExpressions + +from + Type lValueType, Expr rValue, Type lValueEssentialType, EssentialTypeCategory lValueTypeCategory, + Type rValueEssentialType, EssentialTypeCategory rValueTypeCategory, string message +where + not isExcluded(rValue, EssentialTypesPackage::assignmentOfIncompatibleEssentialTypeQuery()) and + isAssignmentToEssentialType(lValueType, rValue) and + lValueEssentialType = lValueType and + lValueTypeCategory = getEssentialTypeCategory(lValueEssentialType) and + rValueEssentialType = getEssentialType(rValue) and + rValueTypeCategory = getEssentialTypeCategory(rValueEssentialType) and + ( + not lValueTypeCategory = rValueTypeCategory and + message = + "Assignment of " + rValueTypeCategory + " value to an object of " + lValueTypeCategory + "." + or + lValueTypeCategory = rValueTypeCategory and + lValueEssentialType.getSize() < rValueEssentialType.getSize() and + message = + "Assignment of value of " + lValueTypeCategory + " of size " + rValueEssentialType.getSize() + + " bytes to an object narrower essential type of size " + lValueEssentialType.getSize() + + " bytes." + ) and + // Exception 1: Constant signed integers can be assigned to unsigned integers in certain cases + not exists(int const | + const = rValue.getValue().toInt() and + rValueTypeCategory = EssentiallySignedType() and + rValueEssentialType.getSize() <= any(IntType t | t.isSigned()).getSize() and + lValueTypeCategory = EssentiallyUnsignedType() and + const >= 0 and + const <= 2.pow(lValueEssentialType.getSize() * 8) + ) +select rValue, message diff --git a/c/misra/src/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql b/c/misra/src/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql new file mode 100644 index 0000000000..d5ef8b6d26 --- /dev/null +++ b/c/misra/src/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql @@ -0,0 +1,59 @@ +/** + * @id c/misra/operands-with-mismatched-essential-type-category + * @name RULE-10-4: Operator with usual arithmetic conversions shall have operands with the same essential type category + * @description Both operands of an operator in which the usual arithmetic conversions are performed + * shall have the same essential type category. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-10-4 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import codingstandards.c.misra.MisraExpressions + +from + OperationWithUsualArithmeticConversions op, Type leftOpEssentialType, Type rightOpEssentialType, + EssentialTypeCategory leftOpTypeCategory, EssentialTypeCategory rightOpTypeCategory, + string message +where + not isExcluded(op, EssentialTypesPackage::operandsWithMismatchedEssentialTypeCategoryQuery()) and + leftOpEssentialType = getEssentialType(op.getLeftOperand()) and + rightOpEssentialType = getEssentialType(op.getRightOperand()) and + leftOpTypeCategory = getEssentialTypeCategory(leftOpEssentialType) and + rightOpTypeCategory = getEssentialTypeCategory(rightOpEssentialType) and + ( + not leftOpTypeCategory = rightOpTypeCategory and + message = + "The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: " + + leftOpTypeCategory + ", right operand: " + rightOpTypeCategory + ")." + or + // This is not technically covered by the rule, but the examples make it clear that this should + // be reported as non-compliant. + leftOpTypeCategory = EssentiallyEnumType() and + rightOpTypeCategory = EssentiallyEnumType() and + not leftOpEssentialType = rightOpEssentialType and + message = + "The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: " + + leftOpEssentialType + ", right operand: " + rightOpEssentialType + ")." + ) and + not ( + // Mismatch is permitted if using "+" or "+=" with one character operand and one integer operand + op.getOperator() = ["+", "+="] and + [leftOpTypeCategory, rightOpTypeCategory] = EssentiallyCharacterType() and + [leftOpTypeCategory, rightOpTypeCategory] = + [EssentiallyUnsignedType().(TEssentialTypeCategory), EssentiallySignedType()] + ) and + not ( + // Mismatch is permitted if using "+" or "+=" with one pointer operand and one integer operand + op.getOperator() = ["-", "-="] and + leftOpTypeCategory = EssentiallyCharacterType() and + rightOpTypeCategory = + [EssentiallyUnsignedType().(TEssentialTypeCategory), EssentiallySignedType()] + ) +select op, message diff --git a/c/misra/src/rules/RULE-10-5/InappropriateEssentialTypeCast.ql b/c/misra/src/rules/RULE-10-5/InappropriateEssentialTypeCast.ql new file mode 100644 index 0000000000..10d54c4fff --- /dev/null +++ b/c/misra/src/rules/RULE-10-5/InappropriateEssentialTypeCast.ql @@ -0,0 +1,77 @@ +/** + * @id c/misra/inappropriate-essential-type-cast + * @name RULE-10-5: The value of an expression should not be cast to an inappropriate essential type + * @description Casting the value of an expression to an inappropriate essential type may lead to + * confusing or unexpected behavior in the way the value is converted. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-10-5 + * maintainability + * correctness + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import codingstandards.c.misra.MisraExpressions + +predicate isIncompatibleEssentialTypeCast(EssentialTypeCategory fromCat, EssentialTypeCategory toCat) { + fromCat = EssentiallyBooleanType() and + toCat = + [ + EssentiallyCharacterType(), EssentiallyEnumType(), EssentiallySignedType(), + EssentiallyUnsignedType(), EssentiallyFloatingType().(TEssentialTypeCategory) + ] + or + fromCat = EssentiallyCharacterType() and + toCat = + [ + EssentiallyBooleanType(), EssentiallyEnumType(), + EssentiallyFloatingType().(TEssentialTypeCategory) + ] + or + fromCat = EssentiallyEnumType() and + toCat = [EssentiallyBooleanType(), EssentiallyEnumType().(TEssentialTypeCategory)] // NOTE only if different enum types + or + fromCat = EssentiallySignedType() and + toCat = [EssentiallyBooleanType(), EssentiallyEnumType().(TEssentialTypeCategory)] + or + fromCat = EssentiallyUnsignedType() and + toCat = [EssentiallyBooleanType(), EssentiallyEnumType().(TEssentialTypeCategory)] + or + fromCat = EssentiallyFloatingType() and + toCat = + [ + EssentiallyBooleanType(), EssentiallyCharacterType(), + EssentiallyEnumType().(TEssentialTypeCategory) + ] +} + +from + Cast c, Type essentialFromType, Type essentialToType, EssentialTypeCategory fromCategory, + EssentialTypeCategory toCategory, string message +where + not isExcluded(c, EssentialTypesPackage::inappropriateEssentialTypeCastQuery()) and + not c.isImplicit() and + essentialFromType = getEssentialTypeBeforeConversions(c.getExpr()) and + essentialToType = c.getType() and + fromCategory = getEssentialTypeCategory(essentialFromType) and + toCategory = getEssentialTypeCategory(essentialToType) and + isIncompatibleEssentialTypeCast(fromCategory, toCategory) and + ( + if fromCategory = EssentiallyEnumType() and toCategory = EssentiallyEnumType() + then + // If from/to enum types, then only report if the essential types are different + not essentialToType = essentialFromType and + message = "Incompatible cast from " + essentialFromType + " to " + essentialToType + "." + else message = "Incompatible cast from " + fromCategory + " to " + toCategory + "." + ) and + not ( + // Exception - casting from `0` or `1` to a boolean type is permitted + (fromCategory = EssentiallySignedType() or fromCategory = EssentiallyUnsignedType()) and + toCategory = EssentiallyBooleanType() and + c.getExpr().getValue().toInt() = [0, 1] + ) +select c, message diff --git a/c/misra/src/rules/RULE-10-6/AssignmentToWiderEssentialType.ql b/c/misra/src/rules/RULE-10-6/AssignmentToWiderEssentialType.ql new file mode 100644 index 0000000000..bc1133c784 --- /dev/null +++ b/c/misra/src/rules/RULE-10-6/AssignmentToWiderEssentialType.ql @@ -0,0 +1,29 @@ +/** + * @id c/misra/assignment-to-wider-essential-type + * @name RULE-10-6: The value of a composite expression shall not be assigned to an object with wider essential type + * @description Assigning a composite expression to an object with wider essential type can cause + * some unexpected conversions. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-10-6 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import codingstandards.c.misra.MisraExpressions + +from CompositeExpression ce, Type lValueType, Type compositeEssentialType +where + not isExcluded(ce, EssentialTypesPackage::assignmentToWiderEssentialTypeQuery()) and + isAssignmentToEssentialType(lValueType, ce) and + compositeEssentialType = getEssentialType(ce) and + lValueType.getSize() > compositeEssentialType.getSize() and + // Assignment to a different type category is prohibited by Rule 10.3, so we only report cases + // where the assignment is to the same type category. + getEssentialTypeCategory(lValueType) = getEssentialTypeCategory(compositeEssentialType) +select ce, "Assignment to wider essential type: $@." diff --git a/c/misra/src/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.ql b/c/misra/src/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.ql new file mode 100644 index 0000000000..1cf20378fa --- /dev/null +++ b/c/misra/src/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.ql @@ -0,0 +1,38 @@ +/** + * @id c/misra/implicit-conversion-of-composite-expression + * @name RULE-10-7: Implicit conversion of composite expression operand to wider essential type + * @description If a composite expression is used as one operand of an operator in which the usual + * arithmetic conversions are performed then the other operand shall not have wider + * essential type. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-10-7 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import codingstandards.c.misra.MisraExpressions + +from + OperationWithUsualArithmeticConversions arith, CompositeExpression compositeOp, Expr otherOp, + Type compositeEssentialType, Type otherOpEssentialType +where + not isExcluded(arith, EssentialTypesPackage::implicitConversionOfCompositeExpressionQuery()) and + arith.getAnOperand() = compositeOp and + arith.getAnOperand() = otherOp and + not otherOp = compositeOp and + compositeEssentialType = getEssentialType(compositeOp) and + otherOpEssentialType = getEssentialType(otherOp) and + compositeEssentialType.getSize() < otherOpEssentialType.getSize() and + // Operands of a different type category in an operation with the usual arithmetic conversions is + // prohibited by Rule 10.4, so we only report cases here where the essential type categories are + // the same + getEssentialTypeCategory(compositeEssentialType) = getEssentialTypeCategory(otherOpEssentialType) +select arith, + "Implicit conversion of $@ from " + compositeEssentialType + " to " + otherOpEssentialType, + compositeOp, "composite op" diff --git a/c/misra/src/rules/RULE-10-8/InappropriateCastOfCompositeExpression.ql b/c/misra/src/rules/RULE-10-8/InappropriateCastOfCompositeExpression.ql new file mode 100644 index 0000000000..8e58ded416 --- /dev/null +++ b/c/misra/src/rules/RULE-10-8/InappropriateCastOfCompositeExpression.ql @@ -0,0 +1,40 @@ +/** + * @id c/misra/inappropriate-cast-of-composite-expression + * @name RULE-10-8: Composite expression explicitly casted to wider or different essential type + * @description The value of a composite expression shall not be cast to a different essential type + * category or a wider essential type. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-10-8 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import codingstandards.c.misra.MisraExpressions + +from + Cast c, CompositeExpression ce, Type castEssentialType, Type compositeExprEssentialType, + EssentialTypeCategory castTypeCategory, EssentialTypeCategory compositeTypeCategory, + string message +where + not isExcluded(ce, EssentialTypesPackage::inappropriateCastOfCompositeExpressionQuery()) and + c = ce.getExplicitlyConverted() and + compositeExprEssentialType = getEssentialTypeBeforeConversions(ce) and + castEssentialType = c.getType() and + castTypeCategory = getEssentialTypeCategory(castEssentialType) and + compositeTypeCategory = getEssentialTypeCategory(compositeExprEssentialType) and + ( + not castTypeCategory = compositeTypeCategory and + message = + "Cast from " + compositeTypeCategory + " to " + castTypeCategory + " changes type category." + or + castTypeCategory = compositeTypeCategory and + castEssentialType.getSize() > compositeExprEssentialType.getSize() and + message = "Cast from " + compositeTypeCategory + " to " + castTypeCategory + " widens type." + ) +select ce, message diff --git a/c/misra/src/rules/RULE-14-1/LoopOverEssentiallyFloatType.ql b/c/misra/src/rules/RULE-14-1/LoopOverEssentiallyFloatType.ql new file mode 100644 index 0000000000..6a0f772f61 --- /dev/null +++ b/c/misra/src/rules/RULE-14-1/LoopOverEssentiallyFloatType.ql @@ -0,0 +1,25 @@ +/** + * @id c/misra/loop-over-essentially-float-type + * @name RULE-14-1: A loop counter shall not have essentially floating type + * @description A floating point loop counter can cause confusing behavior when incremented. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-14-1 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import codingstandards.cpp.Loops + +from ForStmt forLoop, Variable loopIterationVariable +where + not isExcluded(loopIterationVariable, EssentialTypesPackage::loopOverEssentiallyFloatTypeQuery()) and + getAnIterationVariable(forLoop) = loopIterationVariable and + getEssentialTypeCategory(loopIterationVariable.getType()) = EssentiallyFloatingType() +select loopIterationVariable, + "Loop iteration variable " + loopIterationVariable.getName() + " is essentially Floating type." diff --git a/c/misra/src/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.ql b/c/misra/src/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.ql new file mode 100644 index 0000000000..9bbec5c398 --- /dev/null +++ b/c/misra/src/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.ql @@ -0,0 +1,80 @@ +/** + * @id c/misra/memcmp-used-to-compare-null-terminated-strings + * @name RULE-21-14: The Standard Library function memcmp shall not be used to compare null terminated strings + * @description Using memcmp to compare null terminated strings may give unexpected results because + * memcmp compares by size with no consideration for the null terminator. + * @kind path-problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-21-14 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes +import semmle.code.cpp.dataflow.TaintTracking +import DataFlow::PathGraph + +// Data flow from a StringLiteral or from an array of characters, to a memcmp call +class NullTerminatedStringToMemcmpConfiguration extends TaintTracking::Configuration { + NullTerminatedStringToMemcmpConfiguration() { this = "NullTerminatedStringToMemcmpConfiguration" } + + override predicate isSource(DataFlow::Node source) { + source.asExpr() instanceof StringLiteral + or + exists(Variable v, ArrayAggregateLiteral aal | + aal = v.getInitializer().getExpr() and + // The array element type is an essentially character type + getEssentialTypeCategory(aal.getElementType()) = EssentiallyCharacterType() and + // Includes a null terminator somewhere in the array initializer + aal.getElementExpr(_).getValue().toInt() = 0 + | + // For local variables, use the array aggregate literal as the source + aal = source.asExpr() + or + // ArrayAggregateLiterals used as initializers for global variables are not viable sources + // for global data flow, so we instead report variable accesses as sources, where the variable + // is constant or is not assigned in the program + v instanceof GlobalVariable and + source.asExpr() = v.getAnAccess() and + ( + v.isConst() + or + not exists(Expr e | e = v.getAnAssignedValue() and not e = aal) + ) + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(FunctionCall memcmp | + memcmp.getTarget().hasGlobalOrStdName("memcmp") and + sink.asExpr() = memcmp.getArgument([0, 1]) + ) + } +} + +from + FunctionCall memcmp, DataFlow::PathNode source, DataFlow::PathNode sink, + DataFlow::PathNode source1, DataFlow::PathNode arg1, DataFlow::PathNode source2, + DataFlow::PathNode arg2 +where + not isExcluded(memcmp, EssentialTypesPackage::memcmpUsedToCompareNullTerminatedStringsQuery()) and + memcmp.getTarget().hasGlobalOrStdName("memcmp") and + arg1.getNode().asExpr() = memcmp.getArgument(0) and + arg2.getNode().asExpr() = memcmp.getArgument(1) and + // There is a path from a null-terminated string to each argument + exists(NullTerminatedStringToMemcmpConfiguration cfg | + cfg.hasFlowPath(source1, arg1) and + cfg.hasFlowPath(source2, arg2) + ) and + // Produce multiple paths for each result, one for each source/arg pair + ( + source = source1 and sink = arg1 + or + source = source2 and sink = arg2 + ) +select memcmp, source, sink, "memcmp used to compare $@ with $@.", source1, + "null-terminated string", source2, "null-terminated string" diff --git a/c/misra/src/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.ql b/c/misra/src/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.ql new file mode 100644 index 0000000000..1a939e920c --- /dev/null +++ b/c/misra/src/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.ql @@ -0,0 +1,46 @@ +/** + * @id c/misra/memcmp-on-inappropriate-essential-type-args + * @name RULE-21-16: Do not use memcmp on pointers to characters or composite types such as structs and unions + * @description The pointer arguments to the Standard Library function memcmp shall point to either + * a pointer type, an essentially signed type, an essentially unsigned type, an + * essentially Boolean type or an essentially enum type. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-21-16 + * maintainability + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.c.misra.EssentialTypes + +from FunctionCall memcmp, Expr arg, Type argBaseType +where + not isExcluded(arg, EssentialTypesPackage::memcmpOnInappropriateEssentialTypeArgsQuery()) and + memcmp.getTarget().hasGlobalOrStdName("memcmp") and + // Pointer arguments + arg = memcmp.getArgument([0, 1]) and + exists(DerivedType pt | + // Must be a pointer type or array type + ( + pt instanceof PointerType or + pt instanceof ArrayType + ) and + pt = arg.getType() and + argBaseType = pt.getBaseType() and + // Doesn't point to a pointer type + not argBaseType instanceof PointerType and + // Doesn't point to a type which is essentially signed, unsigned, boolean or enum + not exists(EssentialTypeCategory typeCategory | + typeCategory = getEssentialTypeCategory(argBaseType) + | + typeCategory = EssentiallySignedType() or + typeCategory = EssentiallyUnsignedType() or + typeCategory = EssentiallyBooleanType() or + typeCategory = EssentiallyEnumType() + ) + ) +select arg, "Argument is a pointer to " + argBaseType + "." diff --git a/c/misra/test/c/misra/EssentialTypes.expected b/c/misra/test/c/misra/EssentialTypes.expected new file mode 100644 index 0000000000..8bf299bd63 --- /dev/null +++ b/c/misra/test/c/misra/EssentialTypes.expected @@ -0,0 +1,40 @@ +| test.c:4:20:4:20 | 1 | signed char | signed char | essentially Signed type | +| test.c:4:20:4:20 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:5:23:5:23 | 1 | signed char | signed char | essentially Signed type | +| test.c:5:23:5:23 | (unsigned short)... | unsigned short | unsigned short | essentially Unsigned type | +| test.c:6:17:6:18 | 1 | signed char | signed char | essentially Signed type | +| test.c:7:21:7:21 | 1 | signed char | signed char | essentially Signed type | +| test.c:7:21:7:21 | (signed short)... | signed short | signed short | essentially Signed type | +| test.c:8:13:8:16 | 1 | bool | bool | essentially Boolean type | +| test.c:8:13:8:16 | (bool)... | bool | bool | essentially Boolean type | +| test.c:10:3:10:3 | b | bool | bool | essentially Boolean type | +| test.c:10:3:10:11 | ... ? ... : ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:10:7:10:7 | u | unsigned int | unsigned int | essentially Unsigned type | +| test.c:10:11:10:11 | u | unsigned int | unsigned int | essentially Unsigned type | +| test.c:11:3:11:3 | b | bool | bool | essentially Boolean type | +| test.c:11:3:11:11 | ... ? ... : ... | signed int | signed int | essentially Signed type | +| test.c:11:7:11:7 | s | signed int | signed int | essentially Signed type | +| test.c:11:11:11:11 | s | signed int | signed int | essentially Signed type | +| test.c:12:3:12:3 | b | bool | bool | essentially Boolean type | +| test.c:12:3:12:12 | ... ? ... : ... | signed int | signed int | essentially Signed type | +| test.c:12:7:12:7 | s | signed int | signed int | essentially Signed type | +| test.c:12:11:12:12 | (int)... | int | int | essentially Signed type | +| test.c:12:11:12:12 | ss | signed short | signed short | essentially Signed type | +| test.c:13:3:13:3 | b | bool | bool | essentially Boolean type | +| test.c:13:3:13:12 | ... ? ... : ... | signed int | signed int | essentially Signed type | +| test.c:13:7:13:8 | (int)... | int | int | essentially Signed type | +| test.c:13:7:13:8 | ss | signed short | signed short | essentially Signed type | +| test.c:13:12:13:12 | s | signed int | signed int | essentially Signed type | +| test.c:14:3:14:3 | b | bool | bool | essentially Boolean type | +| test.c:14:3:14:12 | ... ? ... : ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:14:7:14:8 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:14:7:14:8 | us | unsigned short | unsigned short | essentially Unsigned type | +| test.c:14:12:14:12 | u | unsigned int | unsigned int | essentially Unsigned type | +| test.c:16:3:16:3 | b | bool | bool | essentially Boolean type | +| test.c:16:3:16:11 | ... ? ... : ... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:16:7:16:7 | (unsigned int)... | unsigned int | unsigned int | essentially Unsigned type | +| test.c:16:7:16:7 | s | signed int | signed int | essentially Signed type | +| test.c:16:11:16:11 | u | unsigned int | unsigned int | essentially Unsigned type | +| test.c:26:3:26:3 | f | float | float | essentially Floating type | +| test.c:27:3:27:5 | f32 | float32_t | float32_t | essentially Floating type | +| test.c:28:3:28:6 | cf32 | float | float | essentially Floating type | diff --git a/c/misra/test/c/misra/EssentialTypes.ql b/c/misra/test/c/misra/EssentialTypes.ql new file mode 100644 index 0000000000..f8fe785727 --- /dev/null +++ b/c/misra/test/c/misra/EssentialTypes.ql @@ -0,0 +1,5 @@ +import codingstandards.c.misra.EssentialTypes + +from Expr e, Type et +where et = getEssentialType(e) +select e, et.getName(), getEssentialTypeBeforeConversions(e).getName(), getEssentialTypeCategory(et) diff --git a/c/misra/test/c/misra/test.c b/c/misra/test/c/misra/test.c new file mode 100644 index 0000000000..8788f7e93a --- /dev/null +++ b/c/misra/test/c/misra/test.c @@ -0,0 +1,29 @@ +#include + +void testConditional() { + unsigned int u = 1; + unsigned short us = 1; + signed int s = 1; + signed short ss = 1; + _Bool b = true; + + b ? u : u; // unsigned int + b ? s : s; // signed int + b ? s : ss; // signed int + b ? ss : s; // signed int + b ? us : u; // unsigned int + + b ? s : u; // unsigned int +} + +void testCategoriesForComplexTypes() { + typedef float float32_t; + typedef const float cfloat32_t; + const float f; + const float32_t f32; + cfloat32_t cf32; + + f; // Should be essentially Floating type + f32; // Should be essentially Floating type + cf32; // Should be essentially Floating type +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected b/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected new file mode 100644 index 0000000000..b04a4ee4aa --- /dev/null +++ b/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.expected @@ -0,0 +1,187 @@ +| test.c:13:3:13:6 | access to array | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:14:3:14:6 | access to array | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:20:3:20:4 | + ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:21:3:21:4 | + ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:22:3:22:5 | + ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:27:3:27:4 | - ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:28:3:28:4 | - ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:29:3:29:5 | - ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:31:3:31:4 | - ... | Operand of essentially Unsigned type will be converted to a signed type with the signedness dependent on the implemented size of int. | +| test.c:34:3:34:7 | ... + ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:36:3:36:8 | ... + ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:41:3:41:7 | ... - ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:43:3:43:8 | ... - ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:48:3:48:7 | ... + ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:50:3:50:8 | ... + ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:55:3:55:7 | ... - ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:57:3:57:8 | ... - ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:62:3:62:5 | ... ++ | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:64:3:64:6 | ... ++ | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:69:3:69:5 | ... -- | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:71:3:71:6 | ... -- | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:76:3:76:5 | ++ ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:78:3:78:6 | ++ ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:83:3:83:5 | -- ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:85:3:85:6 | -- ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:90:3:90:7 | ... * ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:91:3:91:7 | ... * ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:92:3:92:8 | ... * ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:97:3:97:7 | ... / ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:98:3:98:7 | ... / ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:99:3:99:8 | ... / ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:104:3:104:7 | ... * ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:105:3:105:7 | ... * ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:106:3:106:8 | ... * ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:111:3:111:7 | ... / ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:112:3:112:7 | ... / ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:113:3:113:8 | ... / ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:118:3:118:7 | ... % ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:119:3:119:7 | ... % ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:120:3:120:8 | ... % ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:125:3:125:7 | ... % ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:126:3:126:7 | ... % ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:127:3:127:8 | ... % ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:132:3:132:7 | ... < ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:139:3:139:7 | ... > ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:146:3:146:8 | ... <= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:153:3:153:8 | ... >= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:160:3:160:7 | ... < ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:167:3:167:7 | ... > ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:174:3:174:8 | ... <= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:181:3:181:8 | ... >= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:217:3:217:4 | ! ... | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:218:3:218:5 | ! ... | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:219:3:219:4 | ! ... | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:220:3:220:4 | ! ... | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:221:3:221:4 | ! ... | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:224:3:224:11 | ... && ... | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:225:3:225:12 | ... && ... | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:226:3:226:11 | ... && ... | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:227:3:227:11 | ... && ... | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:228:3:228:11 | ... && ... | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:231:3:231:12 | ... \|\| ... | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:232:3:232:13 | ... \|\| ... | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:233:3:233:12 | ... \|\| ... | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:234:3:234:12 | ... \|\| ... | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:235:3:235:12 | ... \|\| ... | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:238:3:238:11 | ... && ... | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:239:3:239:12 | ... && ... | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:240:3:240:11 | ... && ... | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:241:3:241:11 | ... && ... | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:242:3:242:11 | ... && ... | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:245:3:245:12 | ... \|\| ... | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:246:3:246:13 | ... \|\| ... | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:247:3:247:12 | ... \|\| ... | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:248:3:248:12 | ... \|\| ... | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:249:3:249:12 | ... \|\| ... | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:251:3:251:8 | ... << ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:252:3:252:8 | ... << ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:253:3:253:9 | ... << ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:254:3:254:8 | ... << ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:258:3:258:8 | ... >> ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:259:3:259:8 | ... >> ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:260:3:260:9 | ... >> ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:261:3:261:8 | ... >> ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:265:3:265:8 | ... << ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:266:3:266:8 | ... << ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:267:3:267:9 | ... << ... | Right hand operatand of shift operator is essentially Enum Type and not not essentially unsigned. | +| test.c:268:3:268:8 | ... << ... | Right hand operatand of shift operator is essentially Signed type and not not essentially unsigned. | +| test.c:272:3:272:8 | ... >> ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:273:3:273:8 | ... >> ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:274:3:274:9 | ... >> ... | Right hand operatand of shift operator is essentially Enum Type and not not essentially unsigned. | +| test.c:275:3:275:8 | ... >> ... | Right hand operatand of shift operator is essentially Signed type and not not essentially unsigned. | +| test.c:279:3:279:6 | ... & ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:280:3:280:6 | ... & ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:281:3:281:7 | ... & ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:282:3:282:6 | ... & ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:286:3:286:7 | ... \| ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:287:3:287:7 | ... \| ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:288:3:288:8 | ... \| ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:289:3:289:7 | ... \| ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:293:3:293:7 | ... ^ ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:294:3:294:7 | ... ^ ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:295:3:295:8 | ... ^ ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:296:3:296:7 | ... ^ ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:300:3:300:6 | ... & ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:301:3:301:6 | ... & ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:302:3:302:7 | ... & ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:303:3:303:6 | ... & ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:307:3:307:7 | ... \| ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:308:3:308:7 | ... \| ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:309:3:309:8 | ... \| ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:310:3:310:7 | ... \| ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:314:3:314:7 | ... ^ ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:315:3:315:7 | ... ^ ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:316:3:316:8 | ... ^ ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:317:3:317:7 | ... ^ ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:329:3:329:11 | ... ? ... : ... | Operand of essentially Character type type interpreted as a Boolean value. | +| test.c:330:3:330:12 | ... ? ... : ... | Operand of essentially Enum Type type interpreted as a Boolean value. | +| test.c:331:3:331:11 | ... ? ... : ... | Operand of essentially Signed type type interpreted as a Boolean value. | +| test.c:332:3:332:11 | ... ? ... : ... | Operand of essentially Unsigned type type interpreted as a Boolean value. | +| test.c:333:3:333:11 | ... ? ... : ... | Operand of essentially Floating type type interpreted as a Boolean value. | +| test.c:342:3:342:8 | ... += ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:344:3:344:9 | ... += ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:349:3:349:8 | ... -= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:351:3:351:9 | ... -= ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:356:3:356:8 | ... += ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:358:3:358:9 | ... += ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:363:3:363:8 | ... -= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:365:3:365:9 | ... -= ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:370:3:370:8 | ... *= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:371:3:371:8 | ... *= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:372:3:372:9 | ... *= ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:377:3:377:8 | ... /= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:378:3:378:8 | ... /= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:379:3:379:9 | ... /= ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:384:3:384:8 | ... *= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:385:3:385:8 | ... *= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:386:3:386:9 | ... *= ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:391:3:391:8 | ... /= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:392:3:392:8 | ... /= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:393:3:393:9 | ... /= ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:398:3:398:8 | ... %= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:399:3:399:8 | ... %= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:400:3:400:9 | ... %= ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:405:3:405:8 | ... %= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:406:3:406:8 | ... %= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:407:3:407:9 | ... %= ... | Operand of essentially Enum type used in arithmetic operation, but has an implementation defined integer type. | +| test.c:412:3:412:9 | ... <<= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:413:3:413:9 | ... <<= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:414:3:414:10 | ... <<= ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:415:3:415:9 | ... <<= ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:419:3:419:9 | ... >>= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:420:3:420:9 | ... >>= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:421:3:421:10 | ... >>= ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:422:3:422:9 | ... >>= ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:426:3:426:9 | ... <<= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:427:3:427:9 | ... <<= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:428:3:428:10 | ... <<= ... | Right hand operatand of shift operator is essentially Enum Type and not not essentially unsigned. | +| test.c:429:3:429:9 | ... <<= ... | Right hand operatand of shift operator is essentially Signed type and not not essentially unsigned. | +| test.c:433:3:433:9 | ... >>= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:434:3:434:9 | ... >>= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:435:3:435:10 | ... >>= ... | Right hand operatand of shift operator is essentially Enum Type and not not essentially unsigned. | +| test.c:436:3:436:9 | ... >>= ... | Right hand operatand of shift operator is essentially Signed type and not not essentially unsigned. | +| test.c:440:3:440:8 | ... &= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:441:3:441:8 | ... &= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:442:3:442:9 | ... &= ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:443:3:443:8 | ... &= ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:447:3:447:8 | ... ^= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:448:3:448:8 | ... ^= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:449:3:449:9 | ... ^= ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:450:3:450:8 | ... ^= ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:454:3:454:8 | ... \|= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:455:3:455:8 | ... \|= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:456:3:456:9 | ... \|= ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:457:3:457:8 | ... \|= ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:461:3:461:8 | ... &= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:462:3:462:8 | ... &= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:463:3:463:9 | ... &= ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:464:3:464:8 | ... &= ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:468:3:468:8 | ... ^= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:469:3:469:8 | ... ^= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:470:3:470:9 | ... ^= ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:471:3:471:8 | ... ^= ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | +| test.c:475:3:475:8 | ... \|= ... | Operand of essentially Boolean type interpreted as a numeric value. | +| test.c:476:3:476:8 | ... \|= ... | Operand of essentially Charater type interpreted as a numeric value. | +| test.c:477:3:477:9 | ... \|= ... | Bitwise operator applied to operand of essentially Enum Type and not essentially unsigned. | +| test.c:478:3:478:8 | ... \|= ... | Bitwise operator applied to operand of essentially Signed type and not essentially unsigned. | diff --git a/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.qlref b/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.qlref new file mode 100644 index 0000000000..f3120fd81f --- /dev/null +++ b/c/misra/test/rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.qlref @@ -0,0 +1 @@ +rules/RULE-10-1/OperandsOfAnInappropriateEssentialType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.expected b/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.expected new file mode 100644 index 0000000000..35a55919fd --- /dev/null +++ b/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.expected @@ -0,0 +1,5 @@ +| test.c:488:4:488:4 | p | Logical operators should not be used with pointer types. | +| test.c:490:3:490:3 | p | Logical operators should not be used with pointer types. | +| test.c:491:7:491:7 | p | Logical operators should not be used with pointer types. | +| test.c:493:3:493:3 | p | Logical operators should not be used with pointer types. | +| test.c:494:8:494:8 | p | Logical operators should not be used with pointer types. | diff --git a/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.qlref b/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.qlref new file mode 100644 index 0000000000..cec5f51a3a --- /dev/null +++ b/c/misra/test/rules/RULE-10-1/PointerTypeOnLogicalOperator.qlref @@ -0,0 +1 @@ +rules/RULE-10-1/PointerTypeOnLogicalOperator.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-1/test.c b/c/misra/test/rules/RULE-10-1/test.c new file mode 100644 index 0000000000..8945890d4c --- /dev/null +++ b/c/misra/test/rules/RULE-10-1/test.c @@ -0,0 +1,495 @@ +#include "stdbool.h" + +void testInappropriateOperands() { + _Bool b = true; + char c = 'c'; + enum E1 { A, B, C } e1 = A; + signed int s = 100; + unsigned int u = 1; + float f = 1.0; + + int a[20]; + + a[b]; // NON_COMPLIANT + a[c]; // NON_COMPLIANT + a[e1]; // COMPLIANT + a[s]; // COMPLIANT + a[u]; // COMPLIANT + // a[f]; // NON_COMPILABLE + + +b; // NON_COMPLIANT + +c; // NON_COMPLIANT + +e1; // NON_COMPLIANT + +s; // COMPLIANT + +u; // COMPLIANT + +f; // COMPLIANT + + -b; // NON_COMPLIANT + -c; // NON_COMPLIANT + -e1; // NON_COMPLIANT + -s; // COMPLIANT + -u; // NON_COMPLIANT + -f; // COMPLIANT + + 1 + b; // NON_COMPLIANT + 1 + c; // COMPLIANT + 1 + e1; // NON_COMPLIANT + 1 + s; // COMPLIANT + 1 + u; // COMPLIANT + 1 + f; // COMPLIANT + + 1 - b; // NON_COMPLIANT + 1 - c; // COMPLIANT + 1 - e1; // NON_COMPLIANT + 1 - s; // COMPLIANT + 1 - u; // COMPLIANT + 1 - f; // COMPLIANT + + b + 1; // NON_COMPLIANT + c + 1; // COMPLIANT + e1 + 1; // NON_COMPLIANT + s + 1; // COMPLIANT + u + 1; // COMPLIANT + f + 1; // COMPLIANT + + b - 1; // NON_COMPLIANT + c - 1; // COMPLIANT + e1 - 1; // NON_COMPLIANT + s - 1; // COMPLIANT + u - 1; // COMPLIANT + f - 1; // COMPLIANT + + b++; // NON_COMPLIANT + c++; // COMPLIANT + e1++; // NON_COMPLIANT + s++; // COMPLIANT + u++; // COMPLIANT + f++; // COMPLIANT + + b--; // NON_COMPLIANT + c--; // COMPLIANT + e1--; // NON_COMPLIANT + s--; // COMPLIANT + u--; // COMPLIANT + f--; // COMPLIANT + + ++b; // NON_COMPLIANT + ++c; // COMPLIANT + ++e1; // NON_COMPLIANT + ++s; // COMPLIANT + ++u; // COMPLIANT + ++f; // COMPLIANT + + --b; // NON_COMPLIANT + --c; // COMPLIANT + --e1; // NON_COMPLIANT + --s; // COMPLIANT + --u; // COMPLIANT + --f; // COMPLIANT + + 1 * b; // NON_COMPLIANT + 1 * c; // NON_COMPLIANT + 1 * e1; // NON_COMPLIANT + 1 * s; // COMPLIANT + 1 * u; // COMPLIANT + 1 * f; // COMPLIANT + + 1 / b; // NON_COMPLIANT + 1 / c; // NON_COMPLIANT + 1 / e1; // NON_COMPLIANT + 1 / s; // COMPLIANT + 1 / u; // COMPLIANT + 1 / f; // COMPLIANT + + b * 1; // NON_COMPLIANT + c * 1; // NON_COMPLIANT + e1 * 1; // NON_COMPLIANT + s * 1; // COMPLIANT + u * 1; // COMPLIANT + f * 1; // COMPLIANT + + b / 1; // NON_COMPLIANT + c / 1; // NON_COMPLIANT + e1 / 1; // NON_COMPLIANT + s / 1; // COMPLIANT + u / 1; // COMPLIANT + f / 1; // COMPLIANT + + b % 1; // NON_COMPLIANT + c % 1; // NON_COMPLIANT + e1 % 1; // NON_COMPLIANT + s % 1; // COMPLIANT + u % 1; // COMPLIANT + // f % 1; // NON_COMPILABLE + + 1 % b; // NON_COMPLIANT + 1 % c; // NON_COMPLIANT + 1 % e1; // NON_COMPLIANT + 1 % s; // COMPLIANT + 1 % u; // COMPLIANT + // 1 % f; // NON_COMPILABLE + + 1 < b; // NON_COMPLIANT + 1 < c; // COMPLIANT + 1 < e1; // COMPLIANT + 1 < s; // COMPLIANT + 1 < u; // COMPLIANT + 1 < f; // COMPLIANT + + 1 > b; // NON_COMPLIANT + 1 > c; // COMPLIANT + 1 > e1; // COMPLIANT + 1 > s; // COMPLIANT + 1 > u; // COMPLIANT + 1 > f; // COMPLIANT + + 1 <= b; // NON_COMPLIANT + 1 <= c; // COMPLIANT + 1 <= e1; // COMPLIANT + 1 <= s; // COMPLIANT + 1 <= u; // COMPLIANT + 1 <= f; // COMPLIANT + + 1 >= b; // NON_COMPLIANT + 1 >= c; // COMPLIANT + 1 >= e1; // COMPLIANT + 1 >= s; // COMPLIANT + 1 >= u; // COMPLIANT + 1 >= f; // COMPLIANT + + b < 1; // NON_COMPLIANT + c < 1; // COMPLIANT + e1 < 1; // COMPLIANT + s < 1; // COMPLIANT + u < 1; // COMPLIANT + f < 1; // COMPLIANT + + b > 1; // NON_COMPLIANT + c > 1; // COMPLIANT + e1 > 1; // COMPLIANT + s > 1; // COMPLIANT + u > 1; // COMPLIANT + f > 1; // COMPLIANT + + b <= 1; // NON_COMPLIANT + c <= 1; // COMPLIANT + e1 <= 1; // COMPLIANT + s <= 1; // COMPLIANT + u <= 1; // COMPLIANT + f <= 1; // COMPLIANT + + b >= 1; // NON_COMPLIANT + c >= 1; // COMPLIANT + e1 >= 1; // COMPLIANT + s >= 1; // COMPLIANT + u >= 1; // COMPLIANT + f >= 1; // COMPLIANT + + b == 1; // COMPLIANT + c == 1; // COMPLIANT + e1 == 1; // COMPLIANT + s == 1; // COMPLIANT + u == 1; // COMPLIANT + f == 1; // COMPLIANT + + b != 1; // COMPLIANT + c != 1; // COMPLIANT + e1 != 1; // COMPLIANT + s != 1; // COMPLIANT + u != 1; // COMPLIANT + f != 1; // COMPLIANT + + 1 == b; // COMPLIANT + 1 == c; // COMPLIANT + 1 == e1; // COMPLIANT + 1 == s; // COMPLIANT + 1 == u; // COMPLIANT + 1 == f; // COMPLIANT + + 1 != b; // COMPLIANT + 1 != c; // COMPLIANT + 1 != e1; // COMPLIANT + 1 != s; // COMPLIANT + 1 != u; // COMPLIANT + 1 != f; // COMPLIANT + + !b; // COMPLIANT + !c; // NON_COMPLIANT + !e1; // NON_COMPLIANT + !s; // NON_COMPLIANT + !u; // NON_COMPLIANT + !f; // NON_COMPLIANT + + b && true; // COMPLIANT + c && true; // NON_COMPLIANT + e1 && true; // NON_COMPLIANT + s && true; // NON_COMPLIANT + u && true; // NON_COMPLIANT + f && true; // NON_COMPLIANT + + b || false; // COMPLIANT + c || false; // NON_COMPLIANT + e1 || false; // NON_COMPLIANT + s || false; // NON_COMPLIANT + u || false; // NON_COMPLIANT + f || false; // NON_COMPLIANT + + true && b; // COMPLIANT + true && c; // NON_COMPLIANT + true && e1; // NON_COMPLIANT + true && s; // NON_COMPLIANT + true && u; // NON_COMPLIANT + true && f; // NON_COMPLIANT + + false || b; // COMPLIANT + false || c; // NON_COMPLIANT + false || e1; // NON_COMPLIANT + false || s; // NON_COMPLIANT + false || u; // NON_COMPLIANT + false || f; // NON_COMPLIANT + + b << u; // NON_COMPLIANT + c << u; // NON_COMPLIANT + e1 << u; // NON_COMPLIANT + s << u; // NON_COMPLIANT + u << u; // COMPLIANT + // f << u; // NON_COMPILABLE + + b >> u; // NON_COMPLIANT + c >> u; // NON_COMPLIANT + e1 >> u; // NON_COMPLIANT + s >> u; // NON_COMPLIANT + u >> u; // COMPLIANT + // f >> u; // NON_COMPILABLE + + u << b; // NON_COMPLIANT + u << c; // NON_COMPLIANT + u << e1; // NON_COMPLIANT + u << s; // NON_COMPLIANT + u << u; // COMPLIANT + // u << f; // NON_COMPILABLE + + u >> b; // NON_COMPLIANT + u >> c; // NON_COMPLIANT + u >> e1; // NON_COMPLIANT + u >> s; // NON_COMPLIANT + u >> u; // COMPLIANT + // u >> f; // NON_COMPILABLE + + b &u; // NON_COMPLIANT + c &u; // NON_COMPLIANT + e1 &u; // NON_COMPLIANT + s &u; // NON_COMPLIANT + u &u; // COMPLIANT + // f &u; // NON_COMPILABLE + + b | u; // NON_COMPLIANT + c | u; // NON_COMPLIANT + e1 | u; // NON_COMPLIANT + s | u; // NON_COMPLIANT + u | u; // COMPLIANT + // f | u; // NON_COMPILABLE + + b ^ u; // NON_COMPLIANT + c ^ u; // NON_COMPLIANT + e1 ^ u; // NON_COMPLIANT + s ^ u; // NON_COMPLIANT + u ^ u; // COMPLIANT + // f ^ u; // NON_COMPILABLE + + u &b; // NON_COMPLIANT + u &c; // NON_COMPLIANT + u &e1; // NON_COMPLIANT + u &s; // NON_COMPLIANT + u &u; // COMPLIANT + // u &f; // NON_COMPILABLE + + u | b; // NON_COMPLIANT + u | c; // NON_COMPLIANT + u | e1; // NON_COMPLIANT + u | s; // NON_COMPLIANT + u | u; // COMPLIANT + // u | f; // NON_COMPILABLE + + u ^ b; // NON_COMPLIANT + u ^ c; // NON_COMPLIANT + u ^ e1; // NON_COMPLIANT + u ^ s; // NON_COMPLIANT + u ^ u; // COMPLIANT + // u ^ f; // NON_COMPILABLE + + ~b; // NON_COMPLIANT + ~c; // NON_COMPLIANT + ~e1; // NON_COMPLIANT + ~s; // NON_COMPLIANT + ~u; // COMPLIANT + //~f; // NON_COMPILABLE + + b ? 1 : 2; // COMPLIANT + c ? 1 : 2; // NON_COMPLIANT + e1 ? 1 : 2; // NON_COMPLIANT + s ? 1 : 2; // NON_COMPLIANT + u ? 1 : 2; // NON_COMPLIANT + f ? 1 : 2; // NON_COMPLIANT + + b ? b : b; // COMPLIANT + b ? c : c; // COMPLIANT + b ? e1 : e1; // COMPLIANT + b ? s : s; // COMPLIANT + b ? u : u; // COMPLIANT + b ? f : f; // COMPLIANT + + b += 1; // NON_COMPLIANT + c += 1; // COMPLIANT + e1 += 1; // NON_COMPLIANT + s += 1; // COMPLIANT + u += 1; // COMPLIANT + f += 1; // COMPLIANT + + b -= 1; // NON_COMPLIANT + c -= 1; // COMPLIANT + e1 -= 1; // NON_COMPLIANT + s -= 1; // COMPLIANT + u -= 1; // COMPLIANT + f -= 1; // COMPLIANT + + u += b; // NON_COMPLIANT + u += c; // COMPLIANT + u += e1; // NON_COMPLIANT + u += s; // COMPLIANT + u += u; // COMPLIANT + u += f; // COMPLIANT + + u -= b; // NON_COMPLIANT + u -= c; // COMPLIANT + u -= e1; // NON_COMPLIANT + u -= s; // COMPLIANT + u -= u; // COMPLIANT + u -= f; // COMPLIANT + + b *= 1; // NON_COMPLIANT + c *= 1; // NON_COMPLIANT + e1 *= 1; // NON_COMPLIANT + s *= 1; // COMPLIANT + u *= 1; // COMPLIANT + f *= 1; // COMPLIANT + + b /= 1; // NON_COMPLIANT + c /= 1; // NON_COMPLIANT + e1 /= 1; // NON_COMPLIANT + s /= 1; // COMPLIANT + u /= 1; // COMPLIANT + f /= 1; // COMPLIANT + + u *= b; // NON_COMPLIANT + u *= c; // NON_COMPLIANT + u *= e1; // NON_COMPLIANT + u *= s; // COMPLIANT + u *= u; // COMPLIANT + u *= f; // COMPLIANT + + u /= b; // NON_COMPLIANT + u /= c; // NON_COMPLIANT + u /= e1; // NON_COMPLIANT + u /= s; // COMPLIANT + u /= u; // COMPLIANT + u /= f; // COMPLIANT + + b %= 1; // NON_COMPLIANT + c %= 1; // NON_COMPLIANT + e1 %= 1; // NON_COMPLIANT + s %= 1; // COMPLIANT + u %= 1; // COMPLIANT + // f %= 1; // NON_COMPILABLE + + u %= b; // NON_COMPLIANT + u %= c; // NON_COMPLIANT + u %= e1; // NON_COMPLIANT + u %= s; // COMPLIANT + u %= u; // COMPLIANT + // u %= f; // NON_COMPILABLE + + b <<= u; // NON_COMPLIANT + c <<= u; // NON_COMPLIANT + e1 <<= u; // NON_COMPLIANT + s <<= u; // NON_COMPLIANT + u <<= u; // COMPLIANT + // f <<= u; // NON_COMPILABLE + + b >>= u; // NON_COMPLIANT + c >>= u; // NON_COMPLIANT + e1 >>= u; // NON_COMPLIANT + s >>= u; // NON_COMPLIANT + u >>= u; // COMPLIANT + // f >>= u; // NON_COMPILABLE + + u <<= b; // NON_COMPLIANT + u <<= c; // NON_COMPLIANT + u <<= e1; // NON_COMPLIANT + u <<= s; // NON_COMPLIANT + u <<= u; // COMPLIANT + // u <<= f; // NON_COMPILABLE + + u >>= b; // NON_COMPLIANT + u >>= c; // NON_COMPLIANT + u >>= e1; // NON_COMPLIANT + u >>= s; // NON_COMPLIANT + u >>= u; // COMPLIANT + // u >>= f; // NON_COMPILABLE + + b &= u; // NON_COMPLIANT + c &= u; // NON_COMPLIANT + e1 &= u; // NON_COMPLIANT + s &= u; // NON_COMPLIANT + u &= u; // COMPLIANT + // f &= u; // NON_COMPILABLE + + b ^= u; // NON_COMPLIANT + c ^= u; // NON_COMPLIANT + e1 ^= u; // NON_COMPLIANT + s ^= u; // NON_COMPLIANT + u ^= u; // COMPLIANT + // f ^= u; // NON_COMPILABLE + + b |= u; // NON_COMPLIANT + c |= u; // NON_COMPLIANT + e1 |= u; // NON_COMPLIANT + s |= u; // NON_COMPLIANT + u |= u; // COMPLIANT + // f |= u; // NON_COMPILABLE + + u &= b; // NON_COMPLIANT + u &= c; // NON_COMPLIANT + u &= e1; // NON_COMPLIANT + u &= s; // NON_COMPLIANT + u &= u; // COMPLIANT + // u &= f; // NON_COMPILABLE + + u ^= b; // NON_COMPLIANT + u ^= c; // NON_COMPLIANT + u ^= e1; // NON_COMPLIANT + u ^= s; // NON_COMPLIANT + u ^= u; // COMPLIANT + // u ^= f; // NON_COMPILABLE + + u |= b; // NON_COMPLIANT + u |= c; // NON_COMPLIANT + u |= e1; // NON_COMPLIANT + u |= s; // NON_COMPLIANT + u |= u; // COMPLIANT + // u |= f; // NON_COMPILABLE +} + +void pointerType() { + _Bool b = true; + int *p; + + !b; // COMPLIANT + !p; // NON_COMPLIANT + b &&b; // COMPLIANT + p &&b; // NON_COMPLIANT + b &&p; // NON_COMPLIANT + b || b; // COMPLIANT + p || b; // NON_COMPLIANT + b || p; // NON_COMPLIANT +} diff --git a/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.expected b/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.expected new file mode 100644 index 0000000000..0a5c7ae0bb --- /dev/null +++ b/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.expected @@ -0,0 +1,15 @@ +| test.c:15:3:15:11 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:16:3:16:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:17:3:17:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:18:3:18:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:19:3:19:9 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:20:3:20:10 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:21:3:21:10 | ... + ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:27:3:27:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:28:3:28:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:29:3:29:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:30:3:30:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:31:3:31:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:32:3:32:9 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:33:3:33:10 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | +| test.c:34:3:34:10 | ... - ... | Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations | diff --git a/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.qlref b/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.qlref new file mode 100644 index 0000000000..774874eb62 --- /dev/null +++ b/c/misra/test/rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.qlref @@ -0,0 +1 @@ +rules/RULE-10-2/AdditionSubtractionOnEssentiallyCharType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-2/test.c b/c/misra/test/rules/RULE-10-2/test.c new file mode 100644 index 0000000000..186c49226e --- /dev/null +++ b/c/misra/test/rules/RULE-10-2/test.c @@ -0,0 +1,35 @@ +#include + +void testRules() { + _Bool b = true; + enum E1 { A, B, C } e1 = A; + signed int i = 100; + unsigned int u = 100; + float f = 10.0f; + + // Addition cases + i + 'a'; // COMPLIANT + 'a' + i; // COMPLIANT + u + 'a'; // COMPLIANT + 'a' + u; // COMPLIANT + 'a' + 'a'; // NON_COMPLIANT + 'a' + f; // NON_COMPLIANT + f + 'a'; // NON_COMPLIANT + 'a' + b; // NON_COMPLIANT + b + 'a'; // NON_COMPLIANT + 'a' + e1; // NON_COMPLIANT + e1 + 'a'; // NON_COMPLIANT + + // Subtration cases + 'a' - i; // COMPLIANT + 'a' - u; // COMPLIANT + 'a' - 'a'; // COMPLIANT + 'a' - f; // NON_COMPLIANT + i - 'a'; // NON_COMPLIANT + u - 'a'; // NON_COMPLIANT + f - 'a'; // NON_COMPLIANT + b - 'a'; // NON_COMPLIANT + 'a' - b; // NON_COMPLIANT + e1 - 'a'; // NON_COMPLIANT + 'a' - e1; // NON_COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected b/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected new file mode 100644 index 0000000000..3867abd0ca --- /dev/null +++ b/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.expected @@ -0,0 +1,133 @@ +| test.c:11:7:11:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:12:7:12:7 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:13:7:13:7 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:14:7:14:7 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:16:8:16:8 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:18:8:18:8 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:19:8:19:8 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:20:8:20:8 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:22:7:22:7 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:23:7:23:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:25:7:25:7 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:26:7:26:7 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:28:7:28:7 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:29:7:29:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:30:7:30:7 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:32:7:32:7 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:34:7:34:7 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:35:7:35:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:36:7:36:7 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:37:7:37:7 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:49:14:49:15 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:50:14:50:14 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:51:14:51:14 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:52:14:52:14 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:54:17:54:17 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:56:17:56:17 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:57:17:57:17 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:58:17:58:17 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:60:19:60:19 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:61:19:61:20 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:63:19:63:19 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:64:19:64:19 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:66:21:66:21 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:67:21:67:22 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:68:21:68:21 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:70:21:70:21 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:72:14:72:14 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:73:14:73:15 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:74:14:74:14 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:75:14:75:14 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:80:7:80:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:81:7:81:7 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:82:7:82:7 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:83:7:83:7 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:86:7:86:7 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:88:7:88:7 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:89:7:89:7 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:90:7:90:7 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:93:7:93:7 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:94:7:94:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:96:7:96:7 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:97:7:97:7 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:100:7:100:7 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:101:7:101:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:102:7:102:7 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:104:7:104:7 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:107:7:107:7 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:108:7:108:8 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:109:7:109:7 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:110:7:110:7 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:118:7:118:8 | - ... | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:119:7:119:16 | 4294967296 | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:131:8:131:8 | A | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:132:8:132:10 | 100 | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:133:23:133:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:138:8:138:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:140:8:140:10 | 100 | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:141:23:141:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:146:8:146:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:147:8:147:8 | A | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:149:23:149:25 | 200 | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:154:8:154:11 | 1 | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:155:8:155:8 | A | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:174:8:174:8 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:175:8:175:8 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:176:8:176:8 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:177:8:177:8 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:180:8:180:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:182:8:182:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:183:8:183:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:184:8:184:9 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:187:8:187:8 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:188:8:188:8 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:190:8:190:8 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:191:8:191:8 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:194:8:194:8 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:195:8:195:8 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:196:8:196:8 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:198:8:198:8 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:201:8:201:8 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:202:8:202:8 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:203:8:203:8 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:204:8:204:8 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:220:12:220:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:222:12:222:12 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:224:12:224:12 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:226:12:226:12 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:239:12:239:12 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:243:12:243:12 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:245:12:245:12 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:247:12:247:12 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:260:12:260:12 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:262:12:262:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:266:12:266:12 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:268:12:268:12 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:281:12:281:12 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:283:12:283:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:285:12:285:12 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:289:12:289:12 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:302:12:302:12 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:304:12:304:13 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:306:12:306:12 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:308:12:308:12 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | +| test.c:332:10:332:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Boolean type. | +| test.c:333:10:333:10 | s | Assignment of essentially Signed type value to an object of essentially Boolean type. | +| test.c:334:10:334:10 | u | Assignment of essentially Unsigned type value to an object of essentially Boolean type. | +| test.c:335:10:335:10 | f | Assignment of essentially Floating type value to an object of essentially Boolean type. | +| test.c:337:11:337:11 | b | Assignment of essentially Boolean type value to an object of essentially Enum Type. | +| test.c:339:11:339:11 | s | Assignment of essentially Signed type value to an object of essentially Enum Type. | +| test.c:340:11:340:11 | u | Assignment of essentially Unsigned type value to an object of essentially Enum Type. | +| test.c:341:11:341:11 | f | Assignment of essentially Floating type value to an object of essentially Enum Type. | +| test.c:343:10:343:10 | b | Assignment of essentially Boolean type value to an object of essentially Signed type. | +| test.c:344:10:344:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Signed type. | +| test.c:346:10:346:10 | u | Assignment of essentially Unsigned type value to an object of essentially Signed type. | +| test.c:347:10:347:10 | f | Assignment of essentially Floating type value to an object of essentially Signed type. | +| test.c:349:10:349:10 | b | Assignment of essentially Boolean type value to an object of essentially Unsigned type. | +| test.c:350:10:350:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Unsigned type. | +| test.c:351:10:351:10 | s | Assignment of essentially Signed type value to an object of essentially Unsigned type. | +| test.c:353:10:353:10 | f | Assignment of essentially Floating type value to an object of essentially Unsigned type. | +| test.c:355:10:355:10 | b | Assignment of essentially Boolean type value to an object of essentially Floating type. | +| test.c:356:10:356:11 | e1 | Assignment of essentially Enum Type value to an object of essentially Floating type. | +| test.c:357:10:357:10 | s | Assignment of essentially Signed type value to an object of essentially Floating type. | +| test.c:358:10:358:10 | u | Assignment of essentially Unsigned type value to an object of essentially Floating type. | diff --git a/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.qlref b/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.qlref new file mode 100644 index 0000000000..32b138eba6 --- /dev/null +++ b/c/misra/test/rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.qlref @@ -0,0 +1 @@ +rules/RULE-10-3/AssignmentOfIncompatibleEssentialType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-3/test.c b/c/misra/test/rules/RULE-10-3/test.c new file mode 100644 index 0000000000..30ab2985ae --- /dev/null +++ b/c/misra/test/rules/RULE-10-3/test.c @@ -0,0 +1,360 @@ +#include + +void testAssignment() { + _Bool b = true; // COMPLIANT + enum E1 { A, B, C } e1 = A; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + b = false; // COMPLIANT + b = e1; // NON_COMPLIANT + b = s; // NON_COMPLIANT + b = u; // NON_COMPLIANT + b = f; // NON_COMPLIANT + + e1 = b; // NON_COMPLIANT + e1 = e1; // COMPLIANT + e1 = s; // NON_COMPLIANT + e1 = u; // NON_COMPLIANT + e1 = f; // NON_COMPLIANT + + s = b; // NON_COMPLIANT + s = e1; // NON_COMPLIANT + s = s; // COMPLIANT + s = u; // NON_COMPLIANT + s = f; // NON_COMPLIANT + + u = b; // NON_COMPLIANT + u = e1; // NON_COMPLIANT + u = s; // NON_COMPLIANT + u = u; // COMPLIANT + u = f; // NON_COMPLIANT + + f = b; // NON_COMPLIANT + f = e1; // NON_COMPLIANT + f = s; // NON_COMPLIANT + f = u; // NON_COMPLIANT + f = f; // COMPLIANT +} + +void testInitializers() { + _Bool b = true; // COMPLIANT + enum E1 { A, B, C } e1 = A; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + _Bool bb = b; // COMPLIANT + _Bool be = e1; // NON_COMPLIANT + _Bool bs = s; // NON_COMPLIANT + _Bool bu = u; // NON_COMPLIANT + _Bool bf = f; // NON_COMPLIANT + + enum E1 e1b = b; // NON_COMPLIANT + enum E1 e1e = e1; // COMPLIANT + enum E1 e1s = s; // NON_COMPLIANT + enum E1 e1u = u; // NON_COMPLIANT + enum E1 e1f = f; // NON_COMPLIANT + + signed int sb = b; // NON_COMPLIANT + signed int se = e1; // NON_COMPLIANT + signed int ss = s; // COMPLIANT + signed int su = u; // NON_COMPLIANT + signed int sf = f; // NON_COMPLIANT + + unsigned int ub = b; // NON_COMPLIANT + unsigned int ue = e1; // NON_COMPLIANT + unsigned int us = s; // NON_COMPLIANT + unsigned int uu = u; // COMPLIANT + unsigned int uf = f; // NON_COMPLIANT + + float fb = b; // NON_COMPLIANT + float fe = e1; // NON_COMPLIANT + float fs = s; // NON_COMPLIANT + float fu = u; // NON_COMPLIANT + float ff = f; // COMPLIANT + + _Bool ba[5] = { + b, // COMPLIANT + e1, // NON_COMPLIANT + s, // NON_COMPLIANT + u, // NON_COMPLIANT + f // NON_COMPLIANT + }; + enum E1 ea[5] = { + b, // NON_COMPLIANT + e1, // COMPLIANT + s, // NON_COMPLIANT + u, // NON_COMPLIANT + f // NON_COMPLIANT + }; + signed int sa[5] = { + b, // NON_COMPLIANT + e1, // NON_COMPLIANT + s, // COMPLIANT + u, // NON_COMPLIANT + f // NON_COMPLIANT + }; + unsigned int ua[5] = { + b, // NON_COMPLIANT + e1, // NON_COMPLIANT + s, // NON_COMPLIANT + u, // COMPLIANT + f // NON_COMPLIANT + }; + float fa[5] = { + b, // NON_COMPLIANT + e1, // NON_COMPLIANT + s, // NON_COMPLIANT + u, // NON_COMPLIANT + f // COMPLIANT + }; +} + +void testException1() { + unsigned int u = 100; // COMPLIANT - by exception 1 + u = 100; // COMPLIANT - by exception 1 + u = -1; // NON_COMPLIANT - smaller that uint, so exception doesn't apply + u = 4294967296; // NON_COMPLIANT - cannot be stored in an int, so exception + // doesn't apply +} + +void testSwitchCase() { + _Bool b = true; // COMPLIANT + enum E1 { A, B, C } e1 = A; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + switch (b) { + case true: // COMPLIANT + case A: // NON_COMPLIANT + case 100: // NON_COMPLIANT + case ((unsigned int)200): // NON_COMPLIANT + break; // case 1.0f: // NON_COMPILABLE + } + + switch (e1) { + case true: // NON_COMPLIANT + case A: // COMPLIANT + case 100: // NON_COMPLIANT + case ((unsigned int)200): // NON_COMPLIANT + break; // case 1.0f: // NON_COMPILABLE + } + + switch (s) { + case true: // NON_COMPLIANT + case A: // NON_COMPLIANT + case 100: // COMPLIANT + case ((unsigned int)200): // NON_COMPLIANT + break; // case 1.0f: // NON_COMPILABLE + } + + switch (u) { + case true: // NON_COMPLIANT + case A: // NON_COMPLIANT + case 100: // COMPLIANT - by exception 1 + case ((unsigned int)200): // COMPLIANT - by exception 1 + break; // case 1.0f: // NON_COMPILABLE + } +} + +enum EG { EGA, EGB, EGC }; + +void func(_Bool b, enum EG eg, signed int i, unsigned int u, float f); + +void testFunctionCall() { + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + func(b, // COMPLIANT + b, // NON_COMPLIANT + b, // NON_COMPLIANT + b, // NON_COMPLIANT + b // NON_COMPLIANT + ); + + func(e1, // NON_COMPLIANT + e1, // COMPLIANT + e1, // NON_COMPLIANT + e1, // NON_COMPLIANT + e1 // NON_COMPLIANT + ); + + func(s, // NON_COMPLIANT + s, // NON_COMPLIANT + s, // COMPLIANT + s, // NON_COMPLIANT + s // NON_COMPLIANT + ); + + func(u, // NON_COMPLIANT + u, // NON_COMPLIANT + u, // NON_COMPLIANT + u, // COMPLIANT + u // NON_COMPLIANT + ); + + func(f, // NON_COMPLIANT + f, // NON_COMPLIANT + f, // NON_COMPLIANT + f, // NON_COMPLIANT + f // COMPLIANT + ); +} + +_Bool testBoolFunctionReturn(int x) { + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + switch (x) { + case 0: + return b; // COMPLIANT + case 1: + return e1; // NON_COMPLIANT + case 2: + return s; // NON_COMPLIANT + case 3: + return u; // NON_COMPLIANT + default: + return f; // NON_COMPLIANT + } +} + +enum EG testEnumFunctionReturn(int x) { + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + switch (x) { + case 0: + return b; // NON_COMPLIANT + case 1: + return e1; // COMPLIANT + case 2: + return s; // NON_COMPLIANT + case 3: + return u; // NON_COMPLIANT + default: + return f; // NON_COMPLIANT + } +} + +signed int testSignedIntFunctionReturn(int x) { + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + switch (x) { + case 0: + return b; // NON_COMPLIANT + case 1: + return e1; // NON_COMPLIANT + case 2: + return s; // COMPLIANT + case 3: + return u; // NON_COMPLIANT + default: + return f; // NON_COMPLIANT + } +} + +unsigned int testUnsignedIntFunctionReturn(int x) { + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + switch (x) { + case 0: + return b; // NON_COMPLIANT + case 1: + return e1; // NON_COMPLIANT + case 2: + return s; // NON_COMPLIANT + case 3: + return u; // COMPLIANT + default: + return f; // NON_COMPLIANT + } +} + +float testFloatFunctionReturn(int x) { + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + switch (x) { + case 0: + return b; // NON_COMPLIANT + case 1: + return e1; // NON_COMPLIANT + case 2: + return s; // NON_COMPLIANT + case 3: + return u; // NON_COMPLIANT + default: + return f; // COMPLIANT + } +} + +struct S1 { + _Bool b; + enum EG e1; + signed int s; + unsigned int u; + float f; +}; + +void testStructAssignment() { + _Bool b = true; // COMPLIANT + enum EG e1 = EGA; // COMPLIANT + signed int s = 100; // COMPLIANT + unsigned int u = 100; // COMPLIANT - by exception 1 + float f = 10.0f; // COMPLIANT + + struct S1 s1; + + s1.b = b; // COMPLIANT + s1.b = e1; // NON_COMPLIANT + s1.b = s; // NON_COMPLIANT + s1.b = u; // NON_COMPLIANT + s1.b = f; // NON_COMPLIANT + + s1.e1 = b; // NON_COMPLIANT + s1.e1 = e1; // COMPLIANT + s1.e1 = s; // NON_COMPLIANT + s1.e1 = u; // NON_COMPLIANT + s1.e1 = f; // NON_COMPLIANT + + s1.s = b; // NON_COMPLIANT + s1.s = e1; // NON_COMPLIANT + s1.s = s; // COMPLIANT + s1.s = u; // NON_COMPLIANT + s1.s = f; // NON_COMPLIANT + + s1.u = b; // NON_COMPLIANT + s1.u = e1; // NON_COMPLIANT + s1.u = s; // NON_COMPLIANT + s1.u = u; // COMPLIANT + s1.u = f; // NON_COMPLIANT + + s1.f = b; // NON_COMPLIANT + s1.f = e1; // NON_COMPLIANT + s1.f = s; // NON_COMPLIANT + s1.f = u; // NON_COMPLIANT + s1.f = f; // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.expected b/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.expected new file mode 100644 index 0000000000..333c3ad581 --- /dev/null +++ b/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.expected @@ -0,0 +1,10 @@ +| test.c:14:3:14:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Unsigned type, right operand: essentially Signed type). | +| test.c:15:3:15:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Unsigned type). | +| test.c:16:3:16:10 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Unsigned type). | +| test.c:17:3:17:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Floating type, right operand: essentially Signed type). | +| test.c:18:3:18:9 | ... + ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Floating type). | +| test.c:19:3:19:10 | ... += ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Floating type). | +| test.c:27:3:27:9 | ... - ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Character type). | +| test.c:28:3:28:10 | ... -= ... | The operands of this operator with usual arithmetic conversions have mismatched essential types (left operand: essentially Signed type, right operand: essentially Character type). | +| test.c:34:3:34:11 | ... < ... | The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: E1, right operand: E2). | +| test.c:35:3:35:7 | ... < ... | The operands of this operator with usual arithmetic conversions have mismatched essentially Enum types (left operand: E1, right operand: E2). | diff --git a/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.qlref b/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.qlref new file mode 100644 index 0000000000..3b9a9bc32c --- /dev/null +++ b/c/misra/test/rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.qlref @@ -0,0 +1 @@ +rules/RULE-10-4/OperandsWithMismatchedEssentialTypeCategory.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-4/test.c b/c/misra/test/rules/RULE-10-4/test.c new file mode 100644 index 0000000000..666590a2d5 --- /dev/null +++ b/c/misra/test/rules/RULE-10-4/test.c @@ -0,0 +1,36 @@ +void testOps() { + signed int s32 = 100; + signed long long s64 = 100; + unsigned int u = 100; + float f = 10.0f; + char c = 'A'; + + s32 + s32; // COMPLIANT + s64 + s64; // COMPLIANT + s32 + s64; // COMPLIANT + s64 + s32; // COMPLIANT + s64 += s32; // COMPLIANT + s32 += s64; // COMPLIANT + u + s32; // NON_COMPLIANT + s32 + u; // NON_COMPLIANT + s32 += u; // NON_COMPLIANT + f + s32; // NON_COMPLIANT + s32 + f; // NON_COMPLIANT + s32 += f; // NON_COMPLIANT + + c + s32; // COMPLIANT - by exception + c += s32; // COMPLIANT - by exception + s32 + c; // COMPLIANT - by exception + s32 += c; // COMPLIANT - by exception + c - s32; // COMPLIANT - by exception + c -= s32; // COMPLIANT - by exception + s32 - c; // NON_COMPLIANT + s32 -= c; // NON_COMPLIANT + + enum E1 { A, B, C } e1a; + enum E2 { D, E, F } e2a; + e1a < e1a; // COMPLIANT + A < A; // COMPLIANT + e1a < e2a; // NON_COMPLIANT + A < D; // NON_COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.expected b/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.expected new file mode 100644 index 0000000000..731ad9f312 --- /dev/null +++ b/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.expected @@ -0,0 +1,20 @@ +| test.c:9:3:9:9 | (char)... | Incompatible cast from essentially Boolean type to essentially Character type. | +| test.c:10:3:10:13 | (E1)... | Incompatible cast from essentially Boolean type to essentially Enum Type. | +| test.c:11:3:11:15 | (signed int)... | Incompatible cast from essentially Boolean type to essentially Signed type. | +| test.c:12:3:12:17 | (unsigned int)... | Incompatible cast from essentially Boolean type to essentially Unsigned type. | +| test.c:13:3:13:10 | (float)... | Incompatible cast from essentially Boolean type to essentially Floating type. | +| test.c:16:3:16:11 | (bool)... | Incompatible cast from essentially Character type to essentially Boolean type. | +| test.c:18:3:18:13 | (E1)... | Incompatible cast from essentially Character type to essentially Enum Type. | +| test.c:21:3:21:10 | (float)... | Incompatible cast from essentially Character type to essentially Floating type. | +| test.c:24:3:24:11 | (bool)... | Incompatible cast from essentially Enum Type to essentially Boolean type. | +| test.c:26:3:26:13 | (E1)... | Incompatible cast from E2 to E1. | +| test.c:33:3:33:11 | (bool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | +| test.c:35:3:35:13 | (E1)... | Incompatible cast from essentially Signed type to essentially Enum Type. | +| test.c:41:3:41:11 | (bool)... | Incompatible cast from essentially Unsigned type to essentially Boolean type. | +| test.c:43:3:43:13 | (E1)... | Incompatible cast from essentially Unsigned type to essentially Enum Type. | +| test.c:49:3:49:11 | (bool)... | Incompatible cast from essentially Floating type to essentially Boolean type. | +| test.c:50:3:50:9 | (char)... | Incompatible cast from essentially Floating type to essentially Character type. | +| test.c:51:3:51:13 | (E1)... | Incompatible cast from essentially Floating type to essentially Enum Type. | +| test.c:68:3:68:10 | (bool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | +| test.c:72:3:72:16 | (MyBool)... | Incompatible cast from essentially Signed type to essentially Boolean type. | +| test.c:76:3:76:12 | (boolean)... | Incompatible cast from essentially Signed type to essentially Boolean type. | diff --git a/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.qlref b/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.qlref new file mode 100644 index 0000000000..e871beb36b --- /dev/null +++ b/c/misra/test/rules/RULE-10-5/InappropriateEssentialTypeCast.qlref @@ -0,0 +1 @@ +rules/RULE-10-5/InappropriateEssentialTypeCast.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-5/test.c b/c/misra/test/rules/RULE-10-5/test.c new file mode 100644 index 0000000000..dbc5939f0f --- /dev/null +++ b/c/misra/test/rules/RULE-10-5/test.c @@ -0,0 +1,77 @@ +#include + +void testIncompatibleCasts() { + enum E1 { A, B }; + + _Bool b = true; + + (_Bool) b; // COMPLIANT + (char)b; // NON_COMPLIANT + (enum E1) b; // NON_COMPLIANT + (signed int)b; // NON_COMPLIANT + (unsigned int)b; // NON_COMPLIANT + (float)b; // NON_COMPLIANT + + char c = 100; + (_Bool) c; // NON_COMPLIANT + (char)c; // COMPLIANT + (enum E1) c; // NON_COMPLIANT + (signed int)c; // COMPLIANT + (unsigned int)c; // COMPLIANT + (float)c; // NON_COMPLIANT + + enum E2 { C, D } e = C; + (_Bool) e; // NON_COMPLIANT + (char)e; // COMPLIANT + (enum E1) e; // NON_COMPLIANT + (enum E2) e; // COMPLIANT + (signed int)e; // COMPLIANT + (unsigned int)e; // COMPLIANT + (float)e; // COMPLIANT + + signed int i = 100; + (_Bool) i; // NON_COMPLIANT + (char)i; // COMPLIANT + (enum E1) i; // NON_COMPLIANT + (signed int)i; // COMPLIANT + (unsigned int)i; // COMPLIANT + (float)i; // COMPLIANT + + unsigned int u = 100; + (_Bool) u; // NON_COMPLIANT + (char)u; // COMPLIANT + (enum E1) u; // NON_COMPLIANT + (signed int)u; // COMPLIANT + (unsigned int)u; // COMPLIANT + (float)u; // COMPLIANT + + float f = 100.0; + (_Bool) f; // NON_COMPLIANT + (char)f; // NON_COMPLIANT + (enum E1) f; // NON_COMPLIANT + (signed int)f; // COMPLIANT + (unsigned int)f; // COMPLIANT + (float)f; // COMPLIANT +} + +void testImplicit() { + // Implicit conversions are not checked by this rule. + char c = true; // Not covered by rule + _Bool b = 100; // Not covered by rule + unsigned int u = 100; + _Bool b2 = u; // Not covered by rule +} + +void testIntegerConstantBool() { + (_Bool)0; // COMPLIANT + (_Bool)1; // COMPLIANT + (_Bool)2; // NON_COMPLIANT + enum MyBool { f, t }; + (enum MyBool)0; // COMPLIANT + (enum MyBool)1; // COMPLIANT + (enum MyBool)2; // NON_COMPLIANT + typedef int boolean; + (boolean)0; // COMPLIANT + (boolean)1; // COMPLIANT + (boolean)2; // NON_COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-6/AssignmentToWiderEssentialType.expected b/c/misra/test/rules/RULE-10-6/AssignmentToWiderEssentialType.expected new file mode 100644 index 0000000000..0813de0e7c --- /dev/null +++ b/c/misra/test/rules/RULE-10-6/AssignmentToWiderEssentialType.expected @@ -0,0 +1,3 @@ +| test.c:5:9:5:17 | ... + ... | Assignment to wider essential type: $@. | +| test.c:7:24:7:32 | ... + ... | Assignment to wider essential type: $@. | +| test.c:8:27:8:35 | ... + ... | Assignment to wider essential type: $@. | diff --git a/c/misra/test/rules/RULE-10-6/AssignmentToWiderEssentialType.qlref b/c/misra/test/rules/RULE-10-6/AssignmentToWiderEssentialType.qlref new file mode 100644 index 0000000000..5b3ab4e556 --- /dev/null +++ b/c/misra/test/rules/RULE-10-6/AssignmentToWiderEssentialType.qlref @@ -0,0 +1 @@ +rules/RULE-10-6/AssignmentToWiderEssentialType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-6/test.c b/c/misra/test/rules/RULE-10-6/test.c new file mode 100644 index 0000000000..a6ee9da77b --- /dev/null +++ b/c/misra/test/rules/RULE-10-6/test.c @@ -0,0 +1,11 @@ +void testWiderAssignment() { + unsigned int u32 = 100; + unsigned short u16 = 100; + u16 = u16 + u16; // COMPLIANT + u32 = u16 + u16; // NON_COMPLIANT + u32 = (unsigned int)(u16 + u16); // COMPLIANT + unsigned int u32_2 = u16 + u16; // NON_COMPLIANT + unsigned int u32a[1] = {u16 + u16}; // NON_COMPLIANT + + signed int s32 = u16 + u16; // ignored - prohibited by Rule 10.3 +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.expected b/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.expected new file mode 100644 index 0000000000..30b5e1efb7 --- /dev/null +++ b/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.expected @@ -0,0 +1,3 @@ +| test.c:5:3:5:16 | ... + ... | Implicit conversion of $@ from unsigned short to unsigned int | test.c:5:9:5:16 | ... * ... | composite op | +| test.c:6:3:6:18 | ... * ... | Implicit conversion of $@ from unsigned short to unsigned int | test.c:6:9:6:17 | ... + ... | composite op | +| test.c:9:3:9:20 | ... += ... | Implicit conversion of $@ from unsigned short to unsigned int | test.c:9:11:9:19 | ... + ... | composite op | diff --git a/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.qlref b/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.qlref new file mode 100644 index 0000000000..fc83fbb902 --- /dev/null +++ b/c/misra/test/rules/RULE-10-7/ImplicitConversionOfCompositeExpression.qlref @@ -0,0 +1 @@ +rules/RULE-10-7/ImplicitConversionOfCompositeExpression.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-7/test.c b/c/misra/test/rules/RULE-10-7/test.c new file mode 100644 index 0000000000..59d0ed1437 --- /dev/null +++ b/c/misra/test/rules/RULE-10-7/test.c @@ -0,0 +1,14 @@ +void testComposite() { + unsigned int u32 = 100; + unsigned short u16 = 100; + u16 + u32 *u16; // COMPLIANT + u32 + u16 *u16; // NON_COMPLIANT + u32 *(u16 + u16); // NON_COMPLIANT + u32 *(unsigned int)(u16 + u16); // COMPLIANT + u32 + u16 + u16; // COMPLIANT + u32 += (u16 + u16); // NON_COMPLIANT + u32 += (u32 + u16); // COMPLIANT + + signed int s32 = 100; + s32 += (u16 + u16); // // ignored - prohibited by Rule 10.4 +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.expected b/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.expected new file mode 100644 index 0000000000..85e2471a41 --- /dev/null +++ b/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.expected @@ -0,0 +1,4 @@ +| test.c:4:16:4:20 | ... + ... | Cast from essentially Unsigned type to essentially Signed type changes type category. | +| test.c:5:18:5:22 | ... + ... | Cast from essentially Signed type to essentially Unsigned type changes type category. | +| test.c:14:18:14:24 | ... + ... | Cast from essentially Unsigned type to essentially Unsigned type widens type. | +| test.c:20:16:20:22 | ... + ... | Cast from essentially Signed type to essentially Signed type widens type. | diff --git a/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.qlref b/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.qlref new file mode 100644 index 0000000000..58e1592686 --- /dev/null +++ b/c/misra/test/rules/RULE-10-8/InappropriateCastOfCompositeExpression.qlref @@ -0,0 +1 @@ +rules/RULE-10-8/InappropriateCastOfCompositeExpression.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-10-8/test.c b/c/misra/test/rules/RULE-10-8/test.c new file mode 100644 index 0000000000..41efb6b8d8 --- /dev/null +++ b/c/misra/test/rules/RULE-10-8/test.c @@ -0,0 +1,22 @@ +void testDifferentEssentialType() { + unsigned int u = 1; + signed int s = 1; + (signed int)(u + u); // NON_COMPLIANT + (unsigned int)(s + s); // NON_COMPLIANT + (signed int)(s + s); // COMPLIANT + (unsigned int)(u + u); // COMPLIANT +} + +void testWiderType() { + unsigned short us = 1; + unsigned int u = 1; + + (unsigned int)(us + us); // NON_COMPLIANT + (unsigned short)(u + u); // COMPLIANT + + signed short ss = 1; + signed int s = 1; + + (signed int)(ss + ss); // NON_COMPLIANT + (signed short)(s + s); // COMPLIANT +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-14-1/LoopOverEssentiallyFloatType.expected b/c/misra/test/rules/RULE-14-1/LoopOverEssentiallyFloatType.expected new file mode 100644 index 0000000000..0dc7c13836 --- /dev/null +++ b/c/misra/test/rules/RULE-14-1/LoopOverEssentiallyFloatType.expected @@ -0,0 +1,3 @@ +| test.c:4:14:4:14 | f | Loop iteration variable f is essentially Floating type. | +| test.c:6:15:6:15 | d | Loop iteration variable d is essentially Floating type. | +| test.c:8:18:8:18 | f | Loop iteration variable f is essentially Floating type. | diff --git a/c/misra/test/rules/RULE-14-1/LoopOverEssentiallyFloatType.qlref b/c/misra/test/rules/RULE-14-1/LoopOverEssentiallyFloatType.qlref new file mode 100644 index 0000000000..e488267d22 --- /dev/null +++ b/c/misra/test/rules/RULE-14-1/LoopOverEssentiallyFloatType.qlref @@ -0,0 +1 @@ +rules/RULE-14-1/LoopOverEssentiallyFloatType.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-14-1/test.c b/c/misra/test/rules/RULE-14-1/test.c new file mode 100644 index 0000000000..50c2240735 --- /dev/null +++ b/c/misra/test/rules/RULE-14-1/test.c @@ -0,0 +1,15 @@ +typedef float float32_t; + +void test_floating_point_loop() { + for (float f = 0.0F; f < 10.0F; f += 0.2F) { // NON_COMPLIANT + } + for (double d = 0.0F; d < 10.0F; d += 0.2F) { // NON_COMPLIANT + } + for (float32_t f = 0.0F; f < 10.0F; f += 0.2F) { // NON_COMPLIANT + } +} + +void test_non_floating_point_loop() { + for (int i = 0; i < 10; i++) { // COMPLIANT + } +} \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected new file mode 100644 index 0000000000..bdfec99b4a --- /dev/null +++ b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.expected @@ -0,0 +1,34 @@ +edges +| test.c:12:13:12:15 | a | test.c:14:10:14:10 | a | +| test.c:12:13:12:15 | a | test.c:23:13:23:13 | a | +| test.c:12:13:12:15 | a | test.c:24:10:24:10 | a | +| test.c:13:13:13:15 | b | test.c:14:13:14:13 | b | +| test.c:18:15:18:28 | {...} | test.c:21:10:21:10 | e | +| test.c:19:15:19:28 | {...} | test.c:21:13:21:13 | f | +nodes +| test.c:10:10:10:12 | a | semmle.label | a | +| test.c:10:15:10:17 | b | semmle.label | b | +| test.c:12:13:12:15 | a | semmle.label | a | +| test.c:13:13:13:15 | b | semmle.label | b | +| test.c:14:10:14:10 | a | semmle.label | a | +| test.c:14:13:14:13 | b | semmle.label | b | +| test.c:16:10:16:10 | c | semmle.label | c | +| test.c:16:13:16:13 | d | semmle.label | d | +| test.c:18:15:18:28 | {...} | semmle.label | {...} | +| test.c:19:15:19:28 | {...} | semmle.label | {...} | +| test.c:21:10:21:10 | e | semmle.label | e | +| test.c:21:13:21:13 | f | semmle.label | f | +| test.c:23:13:23:13 | a | semmle.label | a | +| test.c:24:10:24:10 | a | semmle.label | a | +| test.c:26:13:26:13 | c | semmle.label | c | +| test.c:27:10:27:10 | c | semmle.label | c | +subpaths +#select +| test.c:10:3:10:8 | call to memcmp | test.c:10:10:10:12 | a | test.c:10:10:10:12 | a | memcmp used to compare $@ with $@. | test.c:10:10:10:12 | a | null-terminated string | test.c:10:15:10:17 | b | null-terminated string | +| test.c:10:3:10:8 | call to memcmp | test.c:10:15:10:17 | b | test.c:10:15:10:17 | b | memcmp used to compare $@ with $@. | test.c:10:10:10:12 | a | null-terminated string | test.c:10:15:10:17 | b | null-terminated string | +| test.c:14:3:14:8 | call to memcmp | test.c:12:13:12:15 | a | test.c:14:10:14:10 | a | memcmp used to compare $@ with $@. | test.c:12:13:12:15 | a | null-terminated string | test.c:13:13:13:15 | b | null-terminated string | +| test.c:14:3:14:8 | call to memcmp | test.c:13:13:13:15 | b | test.c:14:13:14:13 | b | memcmp used to compare $@ with $@. | test.c:12:13:12:15 | a | null-terminated string | test.c:13:13:13:15 | b | null-terminated string | +| test.c:16:3:16:8 | call to memcmp | test.c:16:10:16:10 | c | test.c:16:10:16:10 | c | memcmp used to compare $@ with $@. | test.c:16:10:16:10 | c | null-terminated string | test.c:16:13:16:13 | d | null-terminated string | +| test.c:16:3:16:8 | call to memcmp | test.c:16:13:16:13 | d | test.c:16:13:16:13 | d | memcmp used to compare $@ with $@. | test.c:16:10:16:10 | c | null-terminated string | test.c:16:13:16:13 | d | null-terminated string | +| test.c:21:3:21:8 | call to memcmp | test.c:18:15:18:28 | {...} | test.c:21:10:21:10 | e | memcmp used to compare $@ with $@. | test.c:18:15:18:28 | {...} | null-terminated string | test.c:19:15:19:28 | {...} | null-terminated string | +| test.c:21:3:21:8 | call to memcmp | test.c:19:15:19:28 | {...} | test.c:21:13:21:13 | f | memcmp used to compare $@ with $@. | test.c:18:15:18:28 | {...} | null-terminated string | test.c:19:15:19:28 | {...} | null-terminated string | diff --git a/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.qlref b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.qlref new file mode 100644 index 0000000000..99017569aa --- /dev/null +++ b/c/misra/test/rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.qlref @@ -0,0 +1 @@ +rules/RULE-21-14/MemcmpUsedToCompareNullTerminatedStrings.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-14/test.c b/c/misra/test/rules/RULE-21-14/test.c new file mode 100644 index 0000000000..6ca988242e --- /dev/null +++ b/c/misra/test/rules/RULE-21-14/test.c @@ -0,0 +1,28 @@ +#include + +extern char a[10]; +extern char b[10]; + +char c[10] = {'a', 'b', 0}; +char d[10] = {'a', 'b', 0}; + +void testCmp(int *p) { + memcmp("a", "b", 1); // NON_COMPLIANT + + strcpy(a, "a"); + strcpy(b, "b"); + memcmp(a, b, 1); // NON_COMPLIANT + + memcmp(c, d, 1); // NON_COMPLIANT + + char e[10] = {'a', 'b', 0}; + char f[10] = {'a', 'b', 0}; + + memcmp(e, f, 1); // NON_COMPLIANT + + memcmp(p, a, 1); // COMPLIANT + memcmp(a, p, 1); // COMPLIANT + + memcmp(p, c, 1); // COMPLIANT + memcmp(c, p, 1); // COMPLIANT +} diff --git a/c/misra/test/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.expected b/c/misra/test/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.expected new file mode 100644 index 0000000000..d774a833f2 --- /dev/null +++ b/c/misra/test/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.expected @@ -0,0 +1,10 @@ +| test.c:23:10:23:10 | p | Argument is a pointer to float. | +| test.c:23:13:23:13 | q | Argument is a pointer to float. | +| test.c:35:10:35:10 | p | Argument is a pointer to S1. | +| test.c:35:13:35:13 | q | Argument is a pointer to S1. | +| test.c:41:10:41:10 | p | Argument is a pointer to U. | +| test.c:41:13:41:13 | q | Argument is a pointer to U. | +| test.c:45:10:45:10 | p | Argument is a pointer to char. | +| test.c:45:13:45:13 | q | Argument is a pointer to char. | +| test.c:49:10:49:10 | p | Argument is a pointer to char. | +| test.c:49:13:49:13 | q | Argument is a pointer to char. | diff --git a/c/misra/test/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.qlref b/c/misra/test/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.qlref new file mode 100644 index 0000000000..cf550d800a --- /dev/null +++ b/c/misra/test/rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.qlref @@ -0,0 +1 @@ +rules/RULE-21-16/MemcmpOnInappropriateEssentialTypeArgs.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-21-16/test.c b/c/misra/test/rules/RULE-21-16/test.c new file mode 100644 index 0000000000..f7c4c96707 --- /dev/null +++ b/c/misra/test/rules/RULE-21-16/test.c @@ -0,0 +1,54 @@ +#include +#include + +void testMemcmpSignedInt(signed int *p, signed int *q, size_t size) { + memcmp(p, q, size); // COMPLIANT +} + +void testMemcmpUnsignedInt(unsigned int *p, unsigned int *q, size_t size) { + memcmp(p, q, size); // COMPLIANT +} + +enum E1 { E1_1, E1_2 }; + +void testMemcmpEnum(enum E1 *p, enum E1 *q, size_t size) { + memcmp(p, q, size); // COMPLIANT +} + +void testMemcmpBool(bool *p, bool *q, size_t size) { + memcmp(p, q, size); // COMPLIANT +} + +void testMemcmpFloat(float *p, float *q, size_t size) { + memcmp(p, q, size); // NON_COMPLIANT +} + +void testMemcmpPointerToPointer(void **p, void **q, size_t size) { + memcmp(p, q, size); // COMPLIANT +} + +struct S1 { + int i; +}; + +void testMemcmpStruct(struct S1 *p, struct S1 *q, size_t size) { + memcmp(p, q, size); // NON_COMPLIANT +} + +union U; + +void testMemcmpUnion(union U *p, union U *q, size_t size) { + memcmp(p, q, size); // NON_COMPLIANT +} + +void testMemcmpChar(char *p, char *q, size_t size) { + memcmp(p, q, size); // NON_COMPLIANT +} + +void testMemcmpCharArray(char p[10], char q[10], size_t size) { + memcmp(p, q, size); // NON_COMPLIANT +} + +void testMemcmpIntArray(int p[10], int q[10], size_t size) { + memcmp(p, q, size); // COMPLIANT +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes.qll new file mode 100644 index 0000000000..a29e113146 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/EssentialTypes.qll @@ -0,0 +1,214 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype EssentialTypesQuery = + TOperandsOfAnInappropriateEssentialTypeQuery() or + TPointerTypeOnLogicalOperatorQuery() or + TAdditionSubtractionOnEssentiallyCharTypeQuery() or + TAssignmentOfIncompatibleEssentialTypeQuery() or + TOperandsWithMismatchedEssentialTypeCategoryQuery() or + TInappropriateEssentialTypeCastQuery() or + TAssignmentToWiderEssentialTypeQuery() or + TImplicitConversionOfCompositeExpressionQuery() or + TInappropriateCastOfCompositeExpressionQuery() or + TLoopOverEssentiallyFloatTypeQuery() or + TMemcmpUsedToCompareNullTerminatedStringsQuery() or + TMemcmpOnInappropriateEssentialTypeArgsQuery() + +predicate isEssentialTypesQueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `operandsOfAnInappropriateEssentialType` query + EssentialTypesPackage::operandsOfAnInappropriateEssentialTypeQuery() and + queryId = + // `@id` for the `operandsOfAnInappropriateEssentialType` query + "c/misra/operands-of-an-inappropriate-essential-type" and + ruleId = "RULE-10-1" and + category = "required" + or + query = + // `Query` instance for the `pointerTypeOnLogicalOperator` query + EssentialTypesPackage::pointerTypeOnLogicalOperatorQuery() and + queryId = + // `@id` for the `pointerTypeOnLogicalOperator` query + "c/misra/pointer-type-on-logical-operator" and + ruleId = "RULE-10-1" and + category = "required" + or + query = + // `Query` instance for the `additionSubtractionOnEssentiallyCharType` query + EssentialTypesPackage::additionSubtractionOnEssentiallyCharTypeQuery() and + queryId = + // `@id` for the `additionSubtractionOnEssentiallyCharType` query + "c/misra/addition-subtraction-on-essentially-char-type" and + ruleId = "RULE-10-2" and + category = "required" + or + query = + // `Query` instance for the `assignmentOfIncompatibleEssentialType` query + EssentialTypesPackage::assignmentOfIncompatibleEssentialTypeQuery() and + queryId = + // `@id` for the `assignmentOfIncompatibleEssentialType` query + "c/misra/assignment-of-incompatible-essential-type" and + ruleId = "RULE-10-3" and + category = "required" + or + query = + // `Query` instance for the `operandsWithMismatchedEssentialTypeCategory` query + EssentialTypesPackage::operandsWithMismatchedEssentialTypeCategoryQuery() and + queryId = + // `@id` for the `operandsWithMismatchedEssentialTypeCategory` query + "c/misra/operands-with-mismatched-essential-type-category" and + ruleId = "RULE-10-4" and + category = "required" + or + query = + // `Query` instance for the `inappropriateEssentialTypeCast` query + EssentialTypesPackage::inappropriateEssentialTypeCastQuery() and + queryId = + // `@id` for the `inappropriateEssentialTypeCast` query + "c/misra/inappropriate-essential-type-cast" and + ruleId = "RULE-10-5" and + category = "advisory" + or + query = + // `Query` instance for the `assignmentToWiderEssentialType` query + EssentialTypesPackage::assignmentToWiderEssentialTypeQuery() and + queryId = + // `@id` for the `assignmentToWiderEssentialType` query + "c/misra/assignment-to-wider-essential-type" and + ruleId = "RULE-10-6" and + category = "required" + or + query = + // `Query` instance for the `implicitConversionOfCompositeExpression` query + EssentialTypesPackage::implicitConversionOfCompositeExpressionQuery() and + queryId = + // `@id` for the `implicitConversionOfCompositeExpression` query + "c/misra/implicit-conversion-of-composite-expression" and + ruleId = "RULE-10-7" and + category = "required" + or + query = + // `Query` instance for the `inappropriateCastOfCompositeExpression` query + EssentialTypesPackage::inappropriateCastOfCompositeExpressionQuery() and + queryId = + // `@id` for the `inappropriateCastOfCompositeExpression` query + "c/misra/inappropriate-cast-of-composite-expression" and + ruleId = "RULE-10-8" and + category = "required" + or + query = + // `Query` instance for the `loopOverEssentiallyFloatType` query + EssentialTypesPackage::loopOverEssentiallyFloatTypeQuery() and + queryId = + // `@id` for the `loopOverEssentiallyFloatType` query + "c/misra/loop-over-essentially-float-type" and + ruleId = "RULE-14-1" and + category = "required" + or + query = + // `Query` instance for the `memcmpUsedToCompareNullTerminatedStrings` query + EssentialTypesPackage::memcmpUsedToCompareNullTerminatedStringsQuery() and + queryId = + // `@id` for the `memcmpUsedToCompareNullTerminatedStrings` query + "c/misra/memcmp-used-to-compare-null-terminated-strings" and + ruleId = "RULE-21-14" and + category = "required" + or + query = + // `Query` instance for the `memcmpOnInappropriateEssentialTypeArgs` query + EssentialTypesPackage::memcmpOnInappropriateEssentialTypeArgsQuery() and + queryId = + // `@id` for the `memcmpOnInappropriateEssentialTypeArgs` query + "c/misra/memcmp-on-inappropriate-essential-type-args" and + ruleId = "RULE-21-16" and + category = "required" +} + +module EssentialTypesPackage { + Query operandsOfAnInappropriateEssentialTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `operandsOfAnInappropriateEssentialType` query + TQueryC(TEssentialTypesPackageQuery(TOperandsOfAnInappropriateEssentialTypeQuery())) + } + + Query pointerTypeOnLogicalOperatorQuery() { + //autogenerate `Query` type + result = + // `Query` type for `pointerTypeOnLogicalOperator` query + TQueryC(TEssentialTypesPackageQuery(TPointerTypeOnLogicalOperatorQuery())) + } + + Query additionSubtractionOnEssentiallyCharTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `additionSubtractionOnEssentiallyCharType` query + TQueryC(TEssentialTypesPackageQuery(TAdditionSubtractionOnEssentiallyCharTypeQuery())) + } + + Query assignmentOfIncompatibleEssentialTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `assignmentOfIncompatibleEssentialType` query + TQueryC(TEssentialTypesPackageQuery(TAssignmentOfIncompatibleEssentialTypeQuery())) + } + + Query operandsWithMismatchedEssentialTypeCategoryQuery() { + //autogenerate `Query` type + result = + // `Query` type for `operandsWithMismatchedEssentialTypeCategory` query + TQueryC(TEssentialTypesPackageQuery(TOperandsWithMismatchedEssentialTypeCategoryQuery())) + } + + Query inappropriateEssentialTypeCastQuery() { + //autogenerate `Query` type + result = + // `Query` type for `inappropriateEssentialTypeCast` query + TQueryC(TEssentialTypesPackageQuery(TInappropriateEssentialTypeCastQuery())) + } + + Query assignmentToWiderEssentialTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `assignmentToWiderEssentialType` query + TQueryC(TEssentialTypesPackageQuery(TAssignmentToWiderEssentialTypeQuery())) + } + + Query implicitConversionOfCompositeExpressionQuery() { + //autogenerate `Query` type + result = + // `Query` type for `implicitConversionOfCompositeExpression` query + TQueryC(TEssentialTypesPackageQuery(TImplicitConversionOfCompositeExpressionQuery())) + } + + Query inappropriateCastOfCompositeExpressionQuery() { + //autogenerate `Query` type + result = + // `Query` type for `inappropriateCastOfCompositeExpression` query + TQueryC(TEssentialTypesPackageQuery(TInappropriateCastOfCompositeExpressionQuery())) + } + + Query loopOverEssentiallyFloatTypeQuery() { + //autogenerate `Query` type + result = + // `Query` type for `loopOverEssentiallyFloatType` query + TQueryC(TEssentialTypesPackageQuery(TLoopOverEssentiallyFloatTypeQuery())) + } + + Query memcmpUsedToCompareNullTerminatedStringsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `memcmpUsedToCompareNullTerminatedStrings` query + TQueryC(TEssentialTypesPackageQuery(TMemcmpUsedToCompareNullTerminatedStringsQuery())) + } + + Query memcmpOnInappropriateEssentialTypeArgsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `memcmpOnInappropriateEssentialTypeArgs` query + TQueryC(TEssentialTypesPackageQuery(TMemcmpOnInappropriateEssentialTypeArgsQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index ffb72022e8..9dfb52fb84 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -24,6 +24,7 @@ import Declarations5 import Declarations6 import Declarations7 import Declarations8 +import EssentialTypes import Expressions import IO1 import IO2 @@ -74,6 +75,7 @@ newtype TCQuery = TDeclarations6PackageQuery(Declarations6Query q) or TDeclarations7PackageQuery(Declarations7Query q) or TDeclarations8PackageQuery(Declarations8Query q) or + TEssentialTypesPackageQuery(EssentialTypesQuery q) or TExpressionsPackageQuery(ExpressionsQuery q) or TIO1PackageQuery(IO1Query q) or TIO2PackageQuery(IO2Query q) or @@ -124,6 +126,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isDeclarations6QueryMetadata(query, queryId, ruleId, category) or isDeclarations7QueryMetadata(query, queryId, ruleId, category) or isDeclarations8QueryMetadata(query, queryId, ruleId, category) or + isEssentialTypesQueryMetadata(query, queryId, ruleId, category) or isExpressionsQueryMetadata(query, queryId, ruleId, category) or isIO1QueryMetadata(query, queryId, ruleId, category) or isIO2QueryMetadata(query, queryId, ruleId, category) or diff --git a/rule_packages/c/EssentialTypes.json b/rule_packages/c/EssentialTypes.json new file mode 100644 index 0000000000..57c7ace1ba --- /dev/null +++ b/rule_packages/c/EssentialTypes.json @@ -0,0 +1,234 @@ +{ + "MISRA-C-2012": { + "RULE-10-1": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Using an inappropriate essential type operand may lead to confusing or unexpected behavior when the operand is converted.", + "kind": "problem", + "name": "Operands shall not be of an inappropriate essential type", + "precision": "very-high", + "severity": "warning", + "short_name": "OperandsOfAnInappropriateEssentialType", + "tags": [ + "maintainability" + ] + }, + { + "description": "Using pointer types with logical operators should be avoid because it can cause confusing behavior.", + "kind": "problem", + "name": "Logical operators should not be used with pointer types", + "precision": "very-high", + "severity": "warning", + "short_name": "PointerTypeOnLogicalOperator", + "tags": [ + "correctness" + ] + } + ], + "title": "Operands shall not be of an inappropriate essential type" + }, + "RULE-10-2": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations.", + "kind": "problem", + "name": "Inappropriate use of essentially character type operands in addition and subtraction operations", + "precision": "very-high", + "severity": "error", + "short_name": "AdditionSubtractionOnEssentiallyCharType", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations" + }, + "RULE-10-3": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category.", + "kind": "problem", + "name": "Do not assign to an object with a different essential type category or narrower essential type", + "precision": "very-high", + "severity": "warning", + "short_name": "AssignmentOfIncompatibleEssentialType", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category" + }, + "RULE-10-4": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category.", + "kind": "problem", + "name": "Operator with usual arithmetic conversions shall have operands with the same essential type category", + "precision": "very-high", + "severity": "warning", + "short_name": "OperandsWithMismatchedEssentialTypeCategory", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category" + }, + "RULE-10-5": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "Casting the value of an expression to an inappropriate essential type may lead to confusing or unexpected behavior in the way the value is converted.", + "kind": "problem", + "name": "The value of an expression should not be cast to an inappropriate essential type", + "precision": "very-high", + "severity": "warning", + "short_name": "InappropriateEssentialTypeCast", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "The value of an expression should not be cast to an inappropriate essential type" + }, + "RULE-10-6": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Assigning a composite expression to an object with wider essential type can cause some unexpected conversions.", + "kind": "problem", + "name": "The value of a composite expression shall not be assigned to an object with wider essential type", + "precision": "very-high", + "severity": "warning", + "short_name": "AssignmentToWiderEssentialType", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "The value of a composite expression shall not be assigned to an object with wider essential type" + }, + "RULE-10-7": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "If a composite expression is used as one operand of an operator in which the usual arithmetic conversions are performed then the other operand shall not have wider essential type.", + "kind": "problem", + "name": "Implicit conversion of composite expression operand to wider essential type", + "precision": "very-high", + "severity": "warning", + "short_name": "ImplicitConversionOfCompositeExpression", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "If a composite expression is used as one operand of an operator in which the usual arithmetic conversions are performed then the other operand shall not have wider essential type" + }, + "RULE-10-8": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "The value of a composite expression shall not be cast to a different essential type category or a wider essential type.", + "kind": "problem", + "name": "Composite expression explicitly casted to wider or different essential type", + "precision": "very-high", + "severity": "warning", + "short_name": "InappropriateCastOfCompositeExpression", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "The value of a composite expression shall not be cast to a different essential type category or a wider essential type" + }, + "RULE-14-1": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "A floating point loop counter can cause confusing behavior when incremented.", + "kind": "problem", + "name": "A loop counter shall not have essentially floating type", + "precision": "very-high", + "severity": "warning", + "short_name": "LoopOverEssentiallyFloatType", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "A loop counter shall not have essentially floating type" + }, + "RULE-21-14": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Using memcmp to compare null terminated strings may give unexpected results because memcmp compares by size with no consideration for the null terminator.", + "kind": "path-problem", + "name": "The Standard Library function memcmp shall not be used to compare null terminated strings", + "precision": "very-high", + "severity": "error", + "short_name": "MemcmpUsedToCompareNullTerminatedStrings", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "The Standard Library function memcmp shall not be used to compare null terminated strings" + }, + "RULE-21-16": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "The pointer arguments to the Standard Library function memcmp shall point to either a pointer type, an essentially signed type, an essentially unsigned type, an essentially Boolean type or an essentially enum type.", + "kind": "problem", + "name": "Do not use memcmp on pointers to characters or composite types such as structs and unions", + "precision": "very-high", + "severity": "error", + "short_name": "MemcmpOnInappropriateEssentialTypeArgs", + "tags": [ + "maintainability", + "correctness" + ] + } + ], + "title": "The pointer arguments to the Standard Library function memcmp shall point to either a pointer type, an essentially signed type, an essentially unsigned type, an essentially Boolean type or an essentially enum type" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index 346cc22fa0..36eea96801 100644 --- a/rules.csv +++ b/rules.csv @@ -665,14 +665,14 @@ c,MISRA-C-2012,RULE-9-2,Yes,Required,,,The initializer for an aggregate or union c,MISRA-C-2012,RULE-9-3,Yes,Required,,,Arrays shall not be partially initialized,,Memory1,Medium, c,MISRA-C-2012,RULE-9-4,Yes,Required,,,An element of an object shall not be initialized more than once,,Memory1,Medium, c,MISRA-C-2012,RULE-9-5,Yes,Required,,,Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly,,Memory2,Medium, -c,MISRA-C-2012,RULE-10-1,Yes,Required,,,Operands shall not be of an inappropriate essential type,,Types,Hard, -c,MISRA-C-2012,RULE-10-2,Yes,Required,,,Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations,,Types,Medium, -c,MISRA-C-2012,RULE-10-3,Yes,Required,,,The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category,,Types,Hard, -c,MISRA-C-2012,RULE-10-4,Yes,Required,,,Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category,,Types,Medium, -c,MISRA-C-2012,RULE-10-5,Yes,Advisory,,,The value of an expression should not be cast to an inappropriate essential type,,Types,Medium, -c,MISRA-C-2012,RULE-10-6,Yes,Required,,,The value of a composite expression shall not be assigned to an object with wider essential type,,Types,Medium, -c,MISRA-C-2012,RULE-10-7,Yes,Required,,,If a composite expression is used as one operand of an operator in which the usual arithmetic conversions are performed then the other operand shall not have wider essential type,,Types,Medium, -c,MISRA-C-2012,RULE-10-8,Yes,Required,,,The value of a composite expression shall not be cast to a different essential type category or a wider essential type,,Types,Medium, +c,MISRA-C-2012,RULE-10-1,Yes,Required,,,Operands shall not be of an inappropriate essential type,,EssentialTypes,Hard, +c,MISRA-C-2012,RULE-10-2,Yes,Required,,,Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations,,EssentialTypes,Medium, +c,MISRA-C-2012,RULE-10-3,Yes,Required,,,The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category,,EssentialTypes,Hard, +c,MISRA-C-2012,RULE-10-4,Yes,Required,,,Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category,,EssentialTypes,Medium, +c,MISRA-C-2012,RULE-10-5,Yes,Advisory,,,The value of an expression should not be cast to an inappropriate essential type,,EssentialTypes,Medium, +c,MISRA-C-2012,RULE-10-6,Yes,Required,,,The value of a composite expression shall not be assigned to an object with wider essential type,,EssentialTypes,Medium, +c,MISRA-C-2012,RULE-10-7,Yes,Required,,,If a composite expression is used as one operand of an operator in which the usual arithmetic conversions are performed then the other operand shall not have wider essential type,,EssentialTypes,Medium, +c,MISRA-C-2012,RULE-10-8,Yes,Required,,,The value of a composite expression shall not be cast to a different essential type category or a wider essential type,,EssentialTypes,Medium, c,MISRA-C-2012,RULE-11-1,Yes,Required,,,Conversions shall not be performed between a pointer to a function and any other type,M5-2-6,Pointers1,Import, c,MISRA-C-2012,RULE-11-2,Yes,Required,,,Conversions shall not be performed between a pointer to an incomplete type and any other type,,Pointers1,Easy, c,MISRA-C-2012,RULE-11-3,Yes,Required,,,A cast shall not be performed between a pointer to object type and a pointer to a different object type,,Pointers1,Easy, @@ -693,7 +693,7 @@ c,MISRA-C-2012,RULE-13-3,Yes,Advisory,,,A full expression containing an incremen c,MISRA-C-2012,RULE-13-4,Yes,Advisory,,,The result of an assignment operator should not be used,M6-2-1,SideEffects1,Easy, c,MISRA-C-2012,RULE-13-5,Yes,Required,,,The right hand operand of a logical && or || operator shall not contain persistent side effects,M5-14-1,SideEffects1,Import, c,MISRA-C-2012,RULE-13-6,Yes,Mandatory,,,The operand of the sizeof operator shall not contain any expression which has potential side effects,M5-3-4,SideEffects1,Import, -c,MISRA-C-2012,RULE-14-1,Yes,Required,,,A loop counter shall not have essentially floating type,FLP30-C A6-5-2,Types,Hard, +c,MISRA-C-2012,RULE-14-1,Yes,Required,,,A loop counter shall not have essentially floating type,FLP30-C A6-5-2,EssentialTypes,Hard, c,MISRA-C-2012,RULE-14-2,Yes,Required,,,A for loop shall be well-formed,M6-5-1...M6-5-6,Statements,Medium, c,MISRA-C-2012,RULE-14-3,Yes,Required,,,Controlling expressions shall not be invariant,,Statements,Medium, c,MISRA-C-2012,RULE-14-4,Yes,Required,,,The controlling expression of an if statement and the controlling expression of an iteration-statement shall have essentially Boolean type,A5-0-2,Statements,Medium, @@ -756,9 +756,9 @@ c,MISRA-C-2012,RULE-21-10,Yes,Required,,,The Standard Library time and date func c,MISRA-C-2012,RULE-21-11,Yes,Required,,,The standard header file shall not be used,,Banned,Easy, c,MISRA-C-2012,RULE-21-12,Yes,Advisory,,,The exception handling features of should not be used,,Banned,Easy, c,MISRA-C-2012,RULE-21-13,Yes,Mandatory,,,Any value passed to a function in shall be representable as an unsigned char or be the value EOF,,Types,Medium, -c,MISRA-C-2012,RULE-21-14,Yes,Required,,,The Standard Library function memcmp shall not be used to compare null terminated strings,,Types,Hard, +c,MISRA-C-2012,RULE-21-14,Yes,Required,,,The Standard Library function memcmp shall not be used to compare null terminated strings,,EssentialTypes,Hard, c,MISRA-C-2012,RULE-21-15,Yes,Required,,,"The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers to qualified or unqualified versions of compatible types",,Types,Medium, -c,MISRA-C-2012,RULE-21-16,Yes,Required,,,"The pointer arguments to the Standard Library function memcmp shall point to either a pointer type, an essentially signed type, an essentially unsigned type, an essentially Boolean type or an essentially enum type",,Types,Medium, +c,MISRA-C-2012,RULE-21-16,Yes,Required,,,"The pointer arguments to the Standard Library function memcmp shall point to either a pointer type, an essentially signed type, an essentially unsigned type, an essentially Boolean type or an essentially enum type",,EssentialTypes,Medium, c,MISRA-C-2012,RULE-21-17,Yes,Mandatory,,,Use of the string handling functions from shall not result in accesses beyond the bounds of the objects referenced by their pointer parameters,,Memory2,Hard, c,MISRA-C-2012,RULE-21-18,Yes,Mandatory,,,The size_t argument passed to any function in shall have an appropriate value,,OutOfBounds,Hard, c,MISRA-C-2012,RULE-21-19,Yes,Mandatory,,,"The pointers returned by the Standard Library functions localeconv, getenv, setlocale or, strerror shall only be used as if they have pointer to const-qualified type",ENV30-C,Contracts2,Medium,