FW: RTEMS Software Coding Standard

Manuel Coutinho Manuel.Coutinho at edisoft.pt
Mon Jul 29 08:24:15 UTC 2019

Hi again,

Thank you for your remarks. This is indeed a sensible subject that should be dealt with care.

Today we had a very productive meeting with ESA static analysis expert and Sebastian. I learned quite a bit and would like to share some information with you. Let me just summarize the main points:

 - manual verifications are laborious (very) and miss a lot of rule violations. We don't say that manual verifications cannot be done, but manually verified rules should be instead referred as software coding guidelines (that is, it is not mandatory to verify them).

 - Coverity tool is very good (advertisement aside). At least I got this impression. It gives fewer false-positive violations, has "models" which has models which allow to address false positives in a central and very efficient manner (e.g. see https://github.com/qemu/qemu/blob/master/scripts/coverity-model.c). In the Linux kernel, it has identified 526 issues in the 4.x series alone - if nothing else, this is quite a testimonial. allow to configure the tool much faster.

 - GCC does indeed provide some rules, but the output is not stable (the error/warning message changes from time to time)

 - Clang static analyzer and Cppcheck are more or less similar. That is, they are "moving in the right direction" but provide more false-positive cases, don't offer a functionality like Coverity's "models" to automatically mass-address false positives, and they also have far fewer static analysis checks.

 - FramaC is good for "sound static analysis", that is, it depends on painstaking writing of contracts in ACSL inside special comments in the code. Because of that, the effort involved far exceeds that of addressing bug reports from tools like Coverity. It is indeed the way to go to build "bulletproof" code; but it isn't the 1st step.

My general impression (I think ESA and Sebastian agreed) is that Coverity is "the way to go". It really beats the competition and we have a chance to use it, since ESA can automatically execute the tool on a regular basis. I can't commit to periodicity of the reports but I think it is reasonable to expect daily.

Coverity has a set of rules (MISRA and more) and we should select which ones to use for RTEMS. For example, Sebastian did not want to use the "single return per function" MISRA rule. Coverity rules are public (https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html, search for for MISRA or ISO 26262) so we can check them and pick up what we like.

Sounds like a good approach?

Thank you,

From: Joel Sherrill [mailto:joel at rtems.org]
Sent: quarta-feira, 24 de julho de 2019 18:24
To: Manuel Coutinho
Cc: rtems-devel at rtems.org
Subject: Re: RTEMS Software Coding Standard

On Wed, Jul 24, 2019 at 11:39 AM Manuel Coutinho <Manuel.Coutinho at edisoft.pt> wrote:
Regarding MISRA, we are not suggesting to have all the rules. Only the ones that are automatically verified by a tool that we can use and only those that make sense for the community.
MISRA is not open, that is understood. But there are some sources (https://www.synopsys.com/content/dam/synopsys/sig-assets/datasheets/coverity-misra-standards-ds-ul.pdf) that give a good insight about the rules. I would say that for the rules that are doubtful of their meaning, just leave them out.
Anyway, I suggest to look at cppcheck rules. I send below. They are not exactly written with a "proper rule phrasing" but we can more or less understand their meaning.

The Excel file (proprietary file warning) was inlined and not attached. But which MISRA rules do those correspond to?

Looking through what I can see of the inlined XML, some/many of these are checked by GCC. Why isn't GCC the first order tool? We have been fairly aggressive in enabling warnings and if gcc is already checking for something, that should be the first order tool. If there is value in enabling another warning, that's OK.

What about clang/llvm? Has Gaisler upstreamed their SPARC work? They are usually considered to have good static checking. See http://clang-analyzer.llvm.org/

The code standard should be applicable, at least in the context of the pre-qualification project, to a subset of the RTEMS which we called "space profile" (we don't have the effort to pre-qualify all the RTEMS code). I don't think third party code is inside the space profile.

But any checks need to be consistently integrated into the build mechanics. Perhaps code error checks can be separately defined from more style oriented things that we don't want to apply everywhere.

We are thinking about Coverity or Coverity Scan. Coverity Scan, as I was told, is not a great tool because we don't know which are the rules that are covered and there are no guarantees that one month from now they will remain the same. Coverity might be an issue (or not).

If you have a Coverity license, they may answer questions about what Scan does in comparison.

But ultimately, it is a proprietary tool and even Scan's reports are a pain from an open project perspective.They really can't be depended on for a random submitter to use or even look at. They can only be a back up -- not the primary enforcer of any rule.

We could start with the current RTEMS verifiable rules, but if you look at the excel file, most of the rules that can be automatically verified... I don't know of a tool that verifies them. There are 6 rules that I know that Coverity can check (since they are equivalent to MISRA rules, like the use of /* and */ for comments).

Then we need a table that says we have a rule and no way to automatically verify it so is checked by hand. Or we can verify it with X.

Just checking whatever rules a random tool can check seems like box checking for a contract. Lets try to do the right thing. Just because a rule is checked by hand, doesn't mean the rule doesn't have value and doesn't mean that the rule will never be automatically checked.

I think it would be a very big effort to look at all the rules and cross-check with the tools to find if any tool can verify them. Normally we do the other way around (that is, first we select the tool(s) and derive the rules from it).

Doing this to an open source code base in an open way is not the usual way either. This is new territory.

I think picking a tool and just using a subset of the rules it implements is really backwards. You should know the rules you want to enforce and look for a tool (or tool combination) that covers those rules. Why wouldn't we want an objective set of rules we want to follow?

Random question: Does Frama-C offer anything here?

Anyway, we welcome suggestions or corrections.

I'm not trying to be argumentative. We have rules just not all are enforced by tools. Let's try to change that where possible and if we add rules, try to ensure they are enforced by FLOSS tools.


<?xml version="1.0" encoding="UTF-8"?>
<results>    <error id="toomanyconfigs" severity="style" msg="Too many #ifdef configurations - cppcheck only checks 12 configurations. Use --force to check all configurations. For more details, use --enable=information."/>
    <error id="AssignmentAddressToInteger" severity="style" msg="Assigning a pointer to an integer is not portable."/>
    <error id="AssignmentIntegerToAddress" severity="style" msg="Assigning an integer to a pointer is not portable."/>
    <error id="CastIntegerToAddressAtReturn" severity="style" msg="Returning an integer in a function with pointer return type is not portable."/>
    <error id="CastAddressToIntegerAtReturn" severity="style" msg="Returning an address value in a function with integer return type is not portable."/>
    <error id="assertWithSideEffect" severity="style" msg="Assert statement calls a function which may have desired side effects: 'function'."/>
    <error id="assignmentInAssert" severity="style" msg="Assert statement modifies 'var'."/>
    <error id="autoVariables" severity="error" msg="Address of local auto-variable assigned to a function parameter."/>
    <error id="returnAddressOfAutoVariable" severity="error" msg="Address of an auto-variable returned."/>
    <error id="returnLocalVariable" severity="error" msg="Pointer to local array variable returned."/>
    <error id="returnReference" severity="error" msg="Reference to auto variable returned."/>
    <error id="returnTempReference" severity="error" msg="Reference to temporary returned."/>
    <error id="autovarInvalidDeallocation" severity="error" msg="Deallocation of an auto-variable results in undefined behaviour."/>
    <error id="returnAddressOfFunctionParameter" severity="error" msg="Address of function parameter 'parameter' returned."/>
    <error id="uselessAssignmentArg" severity="style" msg="Assignment of function parameter has no effect outside the function."/>
    <error id="uselessAssignmentPtrArg" severity="style" msg="Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?"/>
    <error id="assignBoolToPointer" severity="error" msg="Boolean value assigned to pointer."/>
    <error id="assignBoolToFloat" severity="style" msg="Boolean value assigned to floating point variable."/>
    <error id="comparisonOfFuncReturningBoolError" severity="style" msg="Comparison of a function returning boolean value using relational (<, >, <= or >=) operator."/>
    <error id="comparisonOfTwoFuncsReturningBoolError" severity="style" msg="Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator."/>
    <error id="comparisonOfBoolWithBoolError" severity="style" msg="Comparison of a variable having boolean value using relational (<, >, <= or >=) operator."/>
    <error id="incrementboolean" severity="style" msg="Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead."/>

    <error id="compareBoolExpressionWithInt" severity="style" msg="Comparison of a boolean expression with an integer other than 0 or 1."/>
    <error id="pointerArithBool" severity="error" msg="Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour."/>
    <error id="boostForeachError" severity="error" msg="BOOST_FOREACH caches the end() iterator. It's undefined behavior if you modify the container inside."/>
    <error id="arrayIndexOutOfBounds" severity="error" msg="Array 'array[2]' index array[1][1] out of bounds."/>
    <error id="bufferAccessOutOfBounds" severity="error" msg="Buffer is accessed out of bounds: buffer"/>
    <error id="strncatUsage" severity="style" msg="Dangerous usage of strncat - 3rd parameter is the maximum number of characters to append."/>
    <error id="outOfBounds" severity="error" msg="index is out of bounds: Supplied size 2 is larger than actual size 1."/>
    <error id="sizeArgumentAsChar" severity="style" msg="The size argument is given as a char constant."/>

    <error id="negativeIndex" severity="error" msg="Array index -1 is out of bounds."/>
    <error id="insecureCmdLineArgs" severity="error" msg="Buffer overrun possible for long command line arguments."/>
    <error id="pointerOutOfBounds" severity="style" msg="Undefined behaviour, pointer arithmetic '' is out of bounds."/>
    <error id="arrayIndexThenCheck" severity="style" msg="Array index 'index' is used before limits check."/>
    <error id="possibleBufferAccessOutOfBounds" severity="style" msg="Possible buffer overflow if strlen(source) is larger than or equal to sizeof(destination)."/>
    <error id="argumentSize" severity="style" msg="The array 'array' is too small, the function 'function' expects a bigger one."/>
    <error id="negativeMemoryAllocationSize" severity="error" msg="Memory allocation size is negative."/>
    <error id="negativeArraySize" severity="error" msg="Declaration of array '' with negative size is undefined behaviour"/>
    <error id="arrayIndexOutOfBoundsCond" severity="style" msg="Array 'x[10]' accessed at index 20, which is out of bounds. Otherwise condition 'y==20' is redundant."/>
    <error id="invalidFunctionArg" severity="error" msg="Invalid func_name() argument nr 1"/>
    <error id="invalidFunctionArgBool" severity="error" msg="Invalid func_name() argument nr 1. A non-boolean value is required."/>
    <error id="ignoredReturnValue" severity="style" msg="Return value of function malloc() is not used."/>
    <error id="wrongmathcall" severity="style" msg="Passing value '#' to #() leads to implementation-defined result."/>
    <error id="unpreciseMathCall" severity="style" msg="Expression '1 - erf(x)' can be replaced by 'erfc(x)' to avoid loss of precision."/>
    <error id="noConstructor" severity="style" msg="The class 'classname' does not have a constructor."/>
    <error id="noExplicitConstructor" severity="style" msg="Class 'classname' has a constructor with 1 argument that is not explicit."/>
    <error id="copyCtorPointerCopying" severity="style" msg="Value of pointer 'var', which points to allocated memory, is copied in copy constructor instead of allocating new memory."/>
    <error id="noCopyConstructor" severity="style" msg="'class class' does not have a copy constructor which is recommended since the class contains a pointer to allocated memory."/>
    <error id="uninitMemberVar" severity="style" msg="Member variable 'classname::varname' is not initialized in the constructor."/>
    <error id="operatorEqVarError" severity="style" msg="Member variable 'classname::' is not assigned a value in 'classname::operator='."/>
    <error id="unusedPrivateFunction" severity="style" msg="Unused private function: 'classname::funcname'"/>
    <error id="memsetClass" severity="error" msg="Using 'memfunc' on class that contains a classname."/>
    <error id="memsetClassReference" severity="error" msg="Using 'memfunc' on class that contains a reference."/>
    <error id="memsetClassFloat" severity="style" msg="Using memset() on class which contains a floating point number."/>
    <error id="mallocOnClassWarning" severity="style" msg="Memory for class instance allocated with malloc(), but class provides constructors."/>
    <error id="mallocOnClassError" severity="error" msg="Memory for class instance allocated with malloc(), but class contains a std::string."/>
    <error id="operatorEq" severity="style" msg="'class::operator=' should return 'class &'."/>
    <error id="virtualDestructor" severity="error" msg="Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor."/>
    <error id="thisSubtraction" severity="style" msg="Suspicious pointer subtraction. Did you intend to write '->'?"/>
    <error id="operatorEqRetRefThis" severity="style" msg="'operator=' should return reference to 'this' instance."/>
    <error id="operatorEqMissingReturnStatement" severity="error" msg="No 'return' statement in non-void function causes undefined behavior."/>
    <error id="operatorEqShouldBeLeftUnimplemented" severity="style" msg="'operator=' should either return reference to 'this' instance or be declared private and left unimplemented."/>
    <error id="operatorEqToSelf" severity="style" msg="'operator=' should check for assignment to self to avoid problems with dynamic memory."/>

    <error id="useInitializationList" severity="style" msg="Variable 'variable' is assigned in constructor body. Consider performing initialization in initialization list."/>
    <error id="selfInitialization" severity="error" msg="Member variable 'var' is initialized by itself."/>
    <error id="duplInheritedMember" severity="style" msg="The class 'class' defines member variable with name 'variable' also defined in its parent class 'class'."/>
    <error id="assignIfError" severity="style" msg="Mismatching assignment and comparison, comparison '' is always false."/>
    <error id="badBitmaskCheck" severity="style" msg="Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?"/>
    <error id="comparisonError" severity="style" msg="Expression '(X & 0x6) == 0x1' is always false."/>
    <error id="multiCondition" severity="style" msg="Expression is always false because 'else if' condition matches previous condition at line 1."/>
    <error id="mismatchingBitAnd" severity="style" msg="Mismatching bitmasks. Result is always 0 (X = Y & 0xf0; Z = X & 0x1; => Z=0)."/>
    <error id="oppositeInnerCondition" severity="style" msg="Opposite conditions in nested 'if' blocks lead to a dead code block."/>
    <error id="incorrectLogicOperator" severity="style" msg="Logical disjunction always evaluates to true: foo > 3 && foo < 4."/>
    <error id="redundantCondition" severity="style" msg="Redundant condition: If x > 11 the condition x > 10 is always true."/>
    <error id="moduloAlwaysTrueFalse" severity="style" msg="Comparison of modulo result is predetermined, because it is always less than 1."/>
    <error id="clarifyCondition" severity="style" msg="Suspicious condition (assignment + comparison); Clarify expression with parentheses."/>
    <error id="knownConditionTrueFalse" severity="style" msg="Condition 'x' is always true"/>
    <error id="invalidTestForOverflow" severity="style" msg="Invalid test for overflow 'x + u < x'. Condition is always false unless there is overflow, and overflow is UB."/>
    <error id="exceptThrowInDestructor" severity="style" msg="Class Class is not safe, destructor throws exception"/>
    <error id="exceptDeallocThrow" severity="style" msg="Exception thrown in invalid state, 'p' points at deallocated memory."/>
    <error id="exceptRethrowCopy" severity="style" msg="Throwing a copy of the caught exception instead of rethrowing the original exception."/>
    <error id="catchExceptionByValue" severity="style" msg="Exception should be caught by reference."/>
    <error id="throwInNoexceptFunction" severity="error" msg="Exception thrown in function declared not to throw exceptions."/>

    <error id="coutCerrMisusage" severity="error" msg="Invalid usage of output stream: '<< std::cout'."/>
    <error id="fflushOnInputStream" severity="style" msg="fflush() called on input stream 'stdin' may result in undefined behaviour on non-linux systems."/>
    <error id="IOWithoutPositioning" severity="error" msg="Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour."/>
    <error id="readWriteOnlyFile" severity="error" msg="Read operation on a file that was opened only for writing."/>
    <error id="writeReadOnlyFile" severity="error" msg="Write operation on a file that was opened only for reading."/>
    <error id="useClosedFile" severity="error" msg="Used file that is not opened."/>
    <error id="seekOnAppendedFile" severity="style" msg="Repositioning operation performed on a file opened in append mode has no effect."/>
    <error id="invalidscanf" severity="style" msg="scanf() without field width limits can crash with huge input data."/>
    <error id="wrongPrintfScanfArgNum" severity="error" msg="printf format string requires 3 parameters but only 2 are given."/>
    <error id="invalidScanfArgType_s" severity="style" msg="%s in format string (no. 1) requires a 'char *' but the argument type is Unknown."/>
    <error id="invalidScanfArgType_int" severity="style" msg="%d in format string (no. 1) requires 'int *' but the argument type is Unknown."/>
    <error id="invalidScanfArgType_float" severity="style" msg="%f in format string (no. 1) requires 'float *' but the argument type is Unknown."/>
    <error id="invalidPrintfArgType_s" severity="style" msg="%s in format string (no. 1) requires 'char *' but the argument type is Unknown."/>
    <error id="invalidPrintfArgType_n" severity="style" msg="%n in format string (no. 1) requires 'int *' but the argument type is Unknown."/>
    <error id="invalidPrintfArgType_p" severity="style" msg="%p in format string (no. 1) requires an address but the argument type is Unknown."/>
    <error id="invalidPrintfArgType_int" severity="style" msg="%X in format string (no. 1) requires 'unsigned int' but the argument type is Unknown."/>
    <error id="invalidPrintfArgType_uint" severity="style" msg="%u in format string (no. 1) requires 'unsigned int' but the argument type is Unknown."/>
    <error id="invalidPrintfArgType_sint" severity="style" msg="%i in format string (no. 1) requires 'int' but the argument type is Unknown."/>
    <error id="invalidPrintfArgType_float" severity="style" msg="%f in format string (no. 1) requires 'double' but the argument type is Unknown."/>
    <error id="invalidLengthModifierError" severity="style" msg="'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier."/>
    <error id="invalidScanfFormatWidth" severity="error" msg="Width 5 given in format string (no. 10) is larger than destination buffer '[0]', use %-1s to prevent overflowing it."/>
    <error id="wrongPrintfScanfParameterPositionError" severity="style" msg="printf: referencing parameter 2 while 1 arguments given"/>
    <error id="deallocret" severity="error" msg="Returning/dereferencing 'p' after it is deallocated / released"/>
    <error id="doubleFree" severity="error" msg="Memory pointed to by 'varname' is freed twice."/>
    <error id="leakNoVarFunctionCall" severity="error" msg="Allocation with funcName, funcName doesn't release it."/>
    <error id="leakReturnValNotUsed" severity="error" msg="Return value of allocation function 'funcName' is not stored."/>

    <error id="publicAllocationError" severity="style" msg="Possible leak in public function. The pointer 'varname' is not deallocated before it is allocated."/>
    <error id="unsafeClassCanLeak" severity="style" msg="Class 'class' is unsafe, 'class::varname' can leak by wrong usage."/>
    <error id="memleak" severity="error" msg="Memory leak: varname"/>
    <error id="resourceLeak" severity="error" msg="Resource leak: varname"/>
    <error id="deallocDealloc" severity="error" msg="Deallocating a deallocated pointer: varname"/>
    <error id="deallocuse" severity="error" msg="Dereferencing 'varname' after it is deallocated / released"/>
    <error id="mismatchSize" severity="error" msg="The allocated size sz is not a multiple of the underlying type's size."/>
    <error id="mismatchAllocDealloc" severity="error" msg="Mismatching allocation and deallocation: varname"/>
    <error id="memleakOnRealloc" severity="error" msg="Common realloc mistake: 'varname' nulled but not freed upon failure"/>
    <error id="nullPointer" severity="error" msg="Null pointer dereference"/>
    <error id="nullPointerDefaultArg" severity="style" msg="Possible null pointer dereference if the default parameter value is used: pointer"/>
    <error id="nullPointerRedundantCheck" severity="style" msg="Either the condition is redundant or there is possible null pointer dereference: pointer."/>
    <error id="zerodiv" severity="error" msg="Division by zero."/>
    <error id="zerodivcond" severity="style" msg="Either the condition is redundant or there is division by zero at line 0."/>
    <error id="unusedScopedObject" severity="style" msg="Instance of 'varname' object is destroyed immediately."/>
    <error id="invalidPointerCast" severity="style" msg="Casting between float* and double* which have an incompatible binary data representation."/>
    <error id="shiftNegative" severity="error" msg="Shifting a negative value is undefined behaviour"/>
    <error id="wrongPipeParameterSize" severity="error" msg="Buffer 'varname' must have size of 2 integers if used as parameter of pipe()."/>
    <error id="raceAfterInterlockedDecrement" severity="error" msg="Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead."/>

    <error id="redundantCopy" severity="style" msg="Buffer 'var' is being written before its old content has been used."/>
    <error id="redundantAssignment" severity="style" msg="Variable 'var' is reassigned a value before the old one has been used."/>
    <error id="comparisonFunctionIsAlwaysTrueOrFalse" severity="style" msg="Comparison of two identical variables with isless(varName,varName) always evaluates to false."/>
    <error id="checkCastIntToCharAndBack" severity="style" msg="Storing func_name() return value in char variable and then comparing with EOF."/>
    <error id="cstyleCast" severity="style" msg="C-style pointer casting"/>
    <error id="passedByValue" severity="style" msg="Function parameter 'parametername' should be passed by reference."/>
    <error id="constStatement" severity="style" msg="Redundant code: Found a statement that begins with type constant."/>
    <error id="signedCharArrayIndex" severity="style" msg="Signed 'char' type used as array index."/>
    <error id="unknownSignCharArrayIndex" severity="style" msg="'char' type used as array index."/>
    <error id="charBitOp" severity="style" msg="When using 'char' variables in bit operations, sign extension can generate unexpected results."/>
    <error id="variableScope" severity="style" msg="The scope of the variable 'varname' can be reduced."/>
    <error id="redundantAssignInSwitch" severity="style" msg="Variable 'var' is reassigned a value before the old one has been used. 'break;' missing?"/>
    <error id="redundantCopyInSwitch" severity="style" msg="Buffer 'var' is being written before its old content has been used. 'break;' missing?"/>

    <error id="selfAssignment" severity="style" msg="Redundant assignment of 'varname' to itself."/>
    <error id="memsetZeroBytes" severity="style" msg="memset() called to fill 0 bytes."/>
    <error id="memsetFloat" severity="style" msg="The 2nd memset() argument 'varname' is a float, its representation is implementation defined."/>
    <error id="memsetValueOutOfRange" severity="style" msg="The 2nd memset() argument 'varname' doesn't fit into an 'unsigned char'."/>
    <error id="clarifyCalculation" severity="style" msg="Clarify calculation precedence for '+' and '?'."/>
    <error id="clarifyStatement" severity="style" msg="Ineffective statement similar to '*A++;'. Did you intend to write '(*A)++;'?"/>

    <error id="duplicateExpression" severity="style" msg="Same expression on both sides of '&&'."/>
    <error id="duplicateExpressionTernary" severity="style" msg="Same expression in both branches of ternary operator."/>
    <error id="duplicateBreak" severity="style" msg="Consecutive return, break, continue, goto or throw statements are unnecessary."/>
    <error id="unreachableCode" severity="style" msg="Statements following return, break, continue, goto or throw will never be executed."/>
    <error id="unsignedLessThanZero" severity="style" msg="Checking if unsigned variable 'varname' is less than zero."/>
    <error id="unsignedPositive" severity="style" msg="Unsigned variable 'varname' can't be negative so it is unnecessary to test it."/>
    <error id="pointerLessThanZero" severity="style" msg="A pointer can not be negative so it is either pointless or an error to check if it is."/>
    <error id="pointerPositive" severity="style" msg="A pointer can not be negative so it is either pointless or an error to check if it is not."/>

    <error id="varFuncNullUB" severity="style" msg="Passing NULL after the last typed argument to a variadic function leads to undefined behaviour."/>
    <error id="nanInArithmeticExpression" severity="style" msg="Using NaN/Inf in a computation."/>
    <error id="commaSeparatedReturn" severity="style" msg="Comma is used in return statement. The comma can easily be misread as a ';'."/>
    <error id="redundantPointerOp" severity="style" msg="Redundant pointer operation on 'varname' - it's already a pointer."/>
    <error id="unusedLabelSwitch" severity="style" msg="Label '' is not used. Should this be a 'case' of the enclosing switch()?"/>
    <error id="unusedLabel" severity="style" msg="Label '' is not used."/>
    <error id="unknownEvaluationOrder" severity="error" msg="Expression 'x = x++;' depends on order of evaluation of side effects"/>
    <error id="invalidIterator1" severity="error" msg="Invalid iterator: iterator"/>
    <error id="iterators" severity="error" msg="Same iterator is used with different containers 'container1' and 'container2'."/>
    <error id="mismatchingContainers" severity="error" msg="Iterators of different containers are used together."/>
    <error id="eraseDereference" severity="error" msg="Invalid iterator 'iter' used."/>
    <error id="stlOutOfBounds" severity="error" msg="When i==foo.size(), foo[i] is out of bounds."/>
    <error id="invalidIterator2" severity="error" msg="After push_back|push_front|insert(), the iterator 'iterator' may be invalid."/>
    <error id="invalidPointer" severity="error" msg="Invalid pointer 'pointer' after push_back()."/>
    <error id="stlBoundaries" severity="error" msg="Dangerous comparison using operator< on iterator."/>
    <error id="stlIfFind" severity="style" msg="Suspicious condition. The result of find() is an iterator, but it is not properly checked."/>
    <error id="stlIfStrFind" severity="style" msg="Inefficient usage of string::find() in condition; string::compare() would be faster."/>
    <error id="stlcstr" severity="error" msg="Dangerous usage of c_str(). The value returned by c_str() is invalid after this call."/>
    <error id="stlcstrReturn" severity="style" msg="Returning the result of c_str() in a function that returns std::string is slow and redundant."/>
    <error id="stlcstrParam" severity="style" msg="Passing the result of c_str() to a function that takes std::string as argument no. 0 is slow and redundant."/>
    <error id="stlSize" severity="style" msg="Possible inefficient checking for 'list' emptiness."/>
    <error id="StlMissingComparison" severity="style" msg="Missing bounds check for extra iterator increment in loop."/>
    <error id="redundantIfRemove" severity="style" msg="Redundant checking of STL container element existence before removing it."/>
    <error id="useAutoPointerCopy" severity="style" msg="Copying 'auto_ptr' pointer to another does not create two equal objects since one has lost its ownership of the pointer."/>
    <error id="useAutoPointerContainer" severity="error" msg="You can randomly lose access to pointers if you store 'auto_ptr' pointers in an STL container."/>
    <error id="useAutoPointerArray" severity="error" msg="Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'."/>
    <error id="useAutoPointerMalloc" severity="error" msg="Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'."/>
    <error id="uselessCallsCompare" severity="style" msg="It is inefficient to call 'str.find(str)' as it always returns 0."/>
    <error id="uselessCallsSwap" severity="style" msg="It is inefficient to swap a object with itself by calling 'str.swap(str)'"/>
    <error id="uselessCallsSubstr" severity="style" msg="Ineffective call of function 'substr' because it returns a copy of the object. Use operator= instead."/>
    <error id="uselessCallsEmpty" severity="style" msg="Ineffective call of function 'empty()'. Did you intend to call 'clear()' instead?"/>
    <error id="uselessCallsRemove" severity="style" msg="Return value of std::remove() ignored. Elements remain in container."/>
    <error id="derefInvalidIterator" severity="style" msg="Possible dereference of an invalid iterator: i"/>

    <error id="sizeofwithsilentarraypointer" severity="style" msg="Using 'sizeof' on array given as function argument returns size of a pointer."/>
    <error id="pointerSize" severity="style" msg="Size of pointer 'varname' used instead of size of its data."/>
    <error id="sizeofDivisionMemfunc" severity="style" msg="Division by result of sizeof(). memset() expects a size in bytes, did you intend to multiply instead?"/>
    <error id="sizeofwithnumericparameter" severity="style" msg="Suspicious usage of 'sizeof' with a numeric constant as parameter."/>
    <error id="sizeofsizeof" severity="style" msg="Calling 'sizeof' on 'sizeof'."/>
    <error id="sizeofCalculation" severity="style" msg="Found calculation inside sizeof()."/>

    <error id="sizeofVoid" severity="style" msg="Behaviour of 'sizeof(void)' is not covered by the ISO C standard."/>
    <error id="sizeofDereferencedVoidPointer" severity="style" msg="'*varname' is of type 'void', the behaviour of 'sizeof(void)' is not covered by the ISO C standard."/>
    <error id="arithOperationsOnVoidPointer" severity="style" msg="'varname' is of type 'vartype'. When using void pointers in calculations, the behaviour is undefined."/>
    <error id="stringLiteralWrite" severity="error" msg="Modifying string literal directly or indirectly is undefined behaviour."/>
    <error id="sprintfOverlappingData" severity="error" msg="Undefined behavior: Variable 'varname' is used as parameter and destination in s[n]printf()."/>
    <error id="strPlusChar" severity="error" msg="Unusual pointer arithmetic. A value of type 'char' is added to a string literal."/>
    <error id="incorrectStringCompare" severity="style" msg="String literal "Hello World" doesn't match length argument for substr()."/>
    <error id="literalWithCharPtrCompare" severity="style" msg="String literal compared with variable 'foo'. Did you intend to use strcmp() instead?"/>
    <error id="charLiteralWithCharPtrCompare" severity="style" msg="Char literal compared with pointer 'foo'. Did you intend to dereference it?"/>
    <error id="incorrectStringBooleanError" severity="style" msg="Conversion of string literal "Hello World" to bool always evaluates to true."/>
    <error id="staticStringCompare" severity="style" msg="Unnecessary comparison of static strings."/>
    <error id="stringCompare" severity="style" msg="Comparison of identical string variables."/>
    <error id="shiftTooManyBits" severity="error" msg="Shifting 32-bit value by 64 bits is undefined behaviour"/>
    <error id="integerOverflow" severity="error" msg="Signed integer overflow for expression ''."/>
    <error id="signConversion" severity="style" msg="Suspicious code: sign conversion of var in calculation, even though var can have a negative value"/>
    <error id="truncLongCastAssignment" severity="style" msg="int result is assigned to long variable. If the variable is long to avoid loss of information, then you have loss of information."/>
    <error id="truncLongCastReturn" severity="style" msg="int result is returned as long value. If the return value is long to avoid loss of information, then you have loss of information."/>
    <error id="uninitstring" severity="error" msg="Dangerous usage of 'varname' (strncpy doesn't always null-terminate it)."/>
    <error id="uninitdata" severity="error" msg="Memory is allocated but not initialized: varname"/>
    <error id="uninitvar" severity="error" msg="Uninitialized variable: varname"/>
    <error id="uninitStructMember" severity="error" msg="Uninitialized struct member: a.b"/>
    <error id="deadpointer" severity="error" msg="Dead pointer usage. Pointer 'pointer' is dead if it has been assigned '&x' at line 0."/>
    <error id="unusedFunction" severity="style" msg="The function 'funcName' is never used."/>
    <error id="unusedVariable" severity="style" msg="Unused variable: varname"/>
    <error id="unusedAllocatedMemory" severity="style" msg="Variable 'varname' is allocated memory that is never used."/>
    <error id="unreadVariable" severity="style" msg="Variable 'varname' is assigned a value that is never used."/>
    <error id="unassignedVariable" severity="style" msg="Variable 'varname' is not assigned a value."/>
    <error id="unusedStructMember" severity="style" msg="struct member 'structname::variable' is never used."/>
    <error id="postfixOperator" severity="style" msg="Prefer prefix ++/-- operators for non-primitive types."/>
    <error id="va_start_wrongParameter" severity="style" msg="'arg1' given to va_start() is not last named argument of the function. Did you intend to pass 'arg2'?"/>
    <error id="va_start_referencePassed" severity="error" msg="Using reference 'arg1' as parameter for va_start() results in undefined behaviour."/>
    <error id="va_end_missing" severity="error" msg="va_list 'vl' was opened but not closed by va_end()."/>
    <error id="va_list_usedBeforeStarted" severity="error" msg="va_list 'vl' used before va_start() was called."/>
    <error id="va_start_subsequentCalls" severity="error" msg="va_start() or va_copy() called subsequently on 'vl' without va_end() in between."/>
    <error id="missingInclude" severity="style" msg="Include file: "" not found."/>
    <error id="missingIncludeSystem" severity="style" msg="Include file: <> not found. Please note: Cppcheck does not need standard library headers to get proper results."/>
    <error file="" line="1" id="ConfigurationNotChecked" severity="style" msg="Skipping configuration 'X' since the value of 'X' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly."/>
    <error id="preprocessorErrorDirective" severity="error" msg="#error message"/>

From: Joel Sherrill [mailto:joel at rtems.org]
Sent: quarta-feira, 24 de julho de 2019 12:10
To: Manuel Coutinho
Cc: rtems-devel at rtems.org
Subject: Re: RTEMS Software Coding Standard

On Wed, Jul 24, 2019, 3:59 AM Manuel Coutinho <Manuel.Coutinho at edisoft.pt> wrote:
Hello all,

It has been some time since my last email. Hope you are doing well!

Some of you already know that Edisoft together with Embedded Brains (and some other institutions) are in a joint project to pre-qualify RTEMS according to the ESA (ECSS) standards.

One of the items required is the Software Coding Standard and one of the goals of the project is to minimize (hopefully eliminate) any deviation from a pre-qualified version of RTEMS and the community RTEMS.

To that end, we ask your ideas of how the RTEMS software coding standard should look like. We have looked at your current coding standard (https://docs.rtems.org/branches/master/eng/coding.html) and made a preliminary analysis to it (see table in attach). For an open-source project, these rules are very good. Unfortunately, from a pre-qualification point of view, there are not so many rules that are verifiable and even fewer that are automatically verifiable by a tool that we can use in the project.

We have some preferences:
 - have only automatically verified tools (to reduce the amount of manual verifications to a minimum)
 - use preferentially open-source tools
 - use at most 2 tools
 - the tool(s) should have a "well-defined" rule set and output (e.g. XML, YAML, whatever) so that the qualification toolchain (another tool that we are developing) can interpret the output and re-format the output to sphinx.

As a side note (please lets not focus on this now), after selecting the rules there could be some violations to the rule and still the pre-qualification be successful. For that, we just need to justify why the violation occurred (was not corrected) and why the code is correct.

We believe a good starting point would be the MISRA rules since they are well defined, lots of tools use them, they can eliminate a lot of errors. But we welcome any other suggestion.
Please keep in mind that some tools, while they are good to use, don't give a well-defined ruleset.

The MISRA C coding guide is not freely available. This is a barrier to open discussion about the merit to adopting the rules.

I personally have not seen the entire rule set in a long time since I don't own a copy. My recollection is that I am against some of the rules. For example, I vaguely recall a rule about 32 character global symbol names and I am strongly opposed to that rule. It reflects limits in long unused object formats. And that's just one I remember as being odd.

Each rule or handful will have to be proposed for evaluation independent of having a copy of MISRA. The way it is checked by a FLOSS tool and its value will have to be established.

The use of any rules which are adopted will have to be restricted to certain directories. We can't change the style or format of third party code.

It is likely close to time to discuss if we will use an annotation like spdx to denote files which have artifacts.

We have looked at cppcheck for some time and only now we found that there is a ruleset. You can get it by running "cppcheck --errorlist".

What's the other tool?

After we define this rule set, we suggest that the current standard (in https://docs.rtems.org/branches/master/eng/coding.html) be more or less renamed to a "Coding guidelines" instead of "Rules" because some of them are not verifiable and we believe the community should keep on following them. And create a new coding standard with the rules that are selected.

And some of those are verifiable. Let's start with those

Kind regards,
Manuel Coutinho
Technical Manager
Aeronautics & Space Systems manuel.coutinho at edisoft.pt
Tel: +351 212 945 906
Fax: +351 212 945 999
Rua Calvet Magalhães, 245
2770-153 Paço de Arcos · Portugal
devel mailing list
devel at rtems.org

More information about the devel mailing list