diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Memory1.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Memory1.qll new file mode 100644 index 000000000..d59212417 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Memory1.qll @@ -0,0 +1,44 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Memory1Query = + TPointerArithmeticFormsAnInvalidPointerQuery() or + TPointerArgumentToCstringFunctionIsInvalidQuery() + +predicate isMemory1QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `pointerArithmeticFormsAnInvalidPointer` query + Memory1Package::pointerArithmeticFormsAnInvalidPointerQuery() and + queryId = + // `@id` for the `pointerArithmeticFormsAnInvalidPointer` query + "cpp/misra/pointer-arithmetic-forms-an-invalid-pointer" and + ruleId = "RULE-8-7-1" and + category = "required" + or + query = + // `Query` instance for the `pointerArgumentToCstringFunctionIsInvalid` query + Memory1Package::pointerArgumentToCstringFunctionIsInvalidQuery() and + queryId = + // `@id` for the `pointerArgumentToCstringFunctionIsInvalid` query + "cpp/misra/pointer-argument-to-cstring-function-is-invalid" and + ruleId = "RULE-8-7-1" and + category = "required" +} + +module Memory1Package { + Query pointerArithmeticFormsAnInvalidPointerQuery() { + //autogenerate `Query` type + result = + // `Query` type for `pointerArithmeticFormsAnInvalidPointer` query + TQueryCPP(TMemory1PackageQuery(TPointerArithmeticFormsAnInvalidPointerQuery())) + } + + Query pointerArgumentToCstringFunctionIsInvalidQuery() { + //autogenerate `Query` type + result = + // `Query` type for `pointerArgumentToCstringFunctionIsInvalid` query + TQueryCPP(TMemory1PackageQuery(TPointerArgumentToCstringFunctionIsInvalidQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll index 0c3cbcc28..115edcf84 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -37,6 +37,7 @@ import Lambdas import Literals import Loops import Macros +import Memory1 import MoveForward import Naming import Null @@ -99,6 +100,7 @@ newtype TCPPQuery = TLiteralsPackageQuery(LiteralsQuery q) or TLoopsPackageQuery(LoopsQuery q) or TMacrosPackageQuery(MacrosQuery q) or + TMemory1PackageQuery(Memory1Query q) or TMoveForwardPackageQuery(MoveForwardQuery q) or TNamingPackageQuery(NamingQuery q) or TNullPackageQuery(NullQuery q) or @@ -161,6 +163,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isLiteralsQueryMetadata(query, queryId, ruleId, category) or isLoopsQueryMetadata(query, queryId, ruleId, category) or isMacrosQueryMetadata(query, queryId, ruleId, category) or + isMemory1QueryMetadata(query, queryId, ruleId, category) or isMoveForwardQueryMetadata(query, queryId, ruleId, category) or isNamingQueryMetadata(query, queryId, ruleId, category) or isNullQueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/common/test/includes/standard-library/cstdlib b/cpp/common/test/includes/standard-library/cstdlib index 3b1eefc4a..0eb1a3e7e 100644 --- a/cpp/common/test/includes/standard-library/cstdlib +++ b/cpp/common/test/includes/standard-library/cstdlib @@ -23,5 +23,8 @@ using ::strtoll; using ::strtoul; using ::strtoull; using ::system; +using ::malloc; +using ::calloc; +using ::realloc; } // namespace std #endif // _GHLIBCPP_CSTDLIB \ No newline at end of file diff --git a/cpp/misra/src/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.ql b/cpp/misra/src/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.ql new file mode 100644 index 000000000..ce9bac81f --- /dev/null +++ b/cpp/misra/src/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.ql @@ -0,0 +1,26 @@ +/** + * @id cpp/misra/pointer-argument-to-cstring-function-is-invalid + * @name RULE-8-7-1: Pointer and index arguments passed to functions in shall not be invalid. + * @description Pointer and index arguments passed to functions in should result in valid + * reads and/or writes. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-8-7-1 + * scope/system + * external/misra/enforcement/undecidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.cert +import codingstandards.c.OutOfBounds + +from + OOB::BufferAccessLibraryFunctionCall fc, string message, Expr bufferArg, string bufferArgStr, + Expr sizeOrOtherBufferArg, string otherStr +where + not isExcluded(fc, OutOfBoundsPackage::libraryFunctionArgumentOutOfBoundsQuery()) and + OOB::problems(fc, message, bufferArg, bufferArgStr, sizeOrOtherBufferArg, otherStr) +select fc, message, bufferArg, bufferArgStr, sizeOrOtherBufferArg, otherStr + diff --git a/cpp/misra/src/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.ql b/cpp/misra/src/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.ql new file mode 100644 index 000000000..bcb13c77b --- /dev/null +++ b/cpp/misra/src/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.ql @@ -0,0 +1,268 @@ +/** + * @id cpp/misra/pointer-arithmetic-forms-an-invalid-pointer + * @name RULE-8-7-1: Pointer arithmetic shall not form an invalid pointer. + * @description Pointers obtained as result of performing arithmetic should point to an initialized + * object, or an element right next to the last element of an array. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/misra/id/rule-8-7-1 + * scope/system + * external/misra/enforcement/undecidable + * external/misra/obligation/required + */ + +import cpp +import codingstandards.cpp.misra +import semmle.code.cpp.dataflow.new.TaintTracking +import semmle.code.cpp.security.BufferAccess + +class ArrayDeclaration extends VariableDeclarationEntry { + int length; + + ArrayDeclaration() { this.getType().getUnderlyingType().(ArrayType).getArraySize() = length } + + /** + * Gets the declared length of this array. + */ + int getLength() { result = length } +} + +class HeapAllocationFunctionCall extends FunctionCall { + AllocationFunction heapAllocFunction; + + HeapAllocationFunctionCall() { this.getTarget() = heapAllocFunction } + + predicate isMallocCall() { heapAllocFunction.getName() = "malloc" } + + predicate isCallocCall() { heapAllocFunction.getName() = "calloc" } + + predicate isReallocCall() { heapAllocFunction.getName() = "realloc" } + + abstract int getMinNumBytes(); +} + +class MallocFunctionCall extends HeapAllocationFunctionCall { + MallocFunctionCall() { this.isMallocCall() } + + override int getMinNumBytes() { result = lowerBound(this.getArgument(0)) } +} + +class CallocFunctionCall extends HeapAllocationFunctionCall { + CallocFunctionCall() { this.isCallocCall() } + + override int getMinNumBytes() { + result = lowerBound(this.getArgument(0)) * lowerBound(this.getArgument(1)) + } +} + +class ReallocFunctionCall extends HeapAllocationFunctionCall { + ReallocFunctionCall() { this.isReallocCall() } + + override int getMinNumBytes() { result = lowerBound(this.getArgument(1)) } +} + +class NarrowedHeapAllocationFunctionCall extends Cast { + HeapAllocationFunctionCall alloc; + + NarrowedHeapAllocationFunctionCall() { alloc = this.getExpr() } + + int getMinNumElements() { + result = alloc.getMinNumBytes() / this.getUnderlyingType().(PointerType).getBaseType().getSize() + } + + HeapAllocationFunctionCall getAllocFunctionCall() { result = alloc } +} + +newtype TArrayAllocation = + TStackAllocation(ArrayDeclaration arrayDecl) or + TDynamicAllocation(NarrowedHeapAllocationFunctionCall narrowedAlloc) + +newtype TPointerFormation = + TArrayExpr(ArrayExprBA arrayExpr) or + TPointerArithmetic(PointerArithmeticOperation pointerArithmetic) + +class ArrayAllocation extends TArrayAllocation { + ArrayDeclaration asStackAllocation() { this = TStackAllocation(result) } + + NarrowedHeapAllocationFunctionCall asDynamicAllocation() { this = TDynamicAllocation(result) } + + string toString() { + result = this.asStackAllocation().toString() or + result = this.asDynamicAllocation().toString() + } + + /** + * Gets the number of the object that the array holds. This number is exact for a stack-allocated + * array, and the minimum estimated value for a heap-allocated one. + */ + int getLength() { + result = this.asStackAllocation().getLength() or + result = this.asDynamicAllocation().getMinNumElements() + } + + Location getLocation() { + result = this.asStackAllocation().getLocation() or + result = this.asDynamicAllocation().getLocation() + } + + DataFlow::Node getNode() { + result.asUninitialized() = this.asStackAllocation().getVariable() or + result.asConvertedExpr() = this.asDynamicAllocation() + } +} + +class PointerFormation extends TPointerFormation { + ArrayExprBA asArrayExpr() { this = TArrayExpr(result) } + + PointerArithmeticOperation asPointerArithmetic() { this = TPointerArithmetic(result) } + + string toString() { + result = this.asArrayExpr().toString() or + result = this.asPointerArithmetic().toString() + } + + int getOffset() { + result = this.asArrayExpr().getArrayOffset().getValue().toInt() + or + exists(PointerAddExpr pointerAddition | pointerAddition = this.asPointerArithmetic() | + result = pointerAddition.getAnOperand().getValue().toInt() // TODO: only get the number being added + ) + or + exists(PointerSubExpr pointerSubtraction | pointerSubtraction = this.asPointerArithmetic() | + result = -pointerSubtraction.getAnOperand().getValue().toInt() + ) + } + + Expr asExpr() { + result = this.asArrayExpr() or + /*.getArrayBase()*/ result = this.asPointerArithmetic() + } + + DataFlow::Node getNode() { result.asExpr() = this.asExpr() } + + Location getLocation() { + result = this.asArrayExpr().getLocation() or + result = this.asPointerArithmetic().getLocation() + } +} + +/** + * NOTE The code in the below module is copied from + * `cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll` in `github/codeql`, commit hash + * `960e990`. This commit hash is the latest of the ones with tag `codeql-cli-2.21.4` which is the CLI version + * compatible with `codeql/cpp-all: 5.0.0` that this query depends on. + */ +module Copied { + import semmle.code.cpp.ir.IR + import semmle.code.cpp.ir.dataflow.internal.SsaInternals as Ssa + + predicate operandToInstructionTaintStep(Operand opFrom, Instruction instrTo) { + // Taint can flow through expressions that alter the value but preserve + // more than one bit of it _or_ expressions that follow data through + // pointer indirections. + instrTo.getAnOperand() = opFrom and + ( + instrTo instanceof ArithmeticInstruction + or + instrTo instanceof BitwiseInstruction + or + instrTo instanceof PointerArithmeticInstruction + ) + or + // Taint flow from an address to its dereference. + Ssa::isDereference(instrTo, opFrom, _) + or + // Unary instructions tend to preserve enough information in practice that we + // want taint to flow through. + // The exception is `FieldAddressInstruction`. Together with the rules below for + // `LoadInstruction`s and `ChiInstruction`s, flow through `FieldAddressInstruction` + // could cause flow into one field to come out an unrelated field. + // This would happen across function boundaries, where the IR would not be able to + // match loads to stores. + instrTo.(UnaryInstruction).getUnaryOperand() = opFrom and + ( + not instrTo instanceof FieldAddressInstruction + or + instrTo.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union + ) + or + // Taint from int to boolean casts. This ensures that we have flow to `!x` in: + // ```cpp + // x = integer_source(); + // if(!x) { ... } + // ``` + exists(Operand zero | + zero.getDef().(ConstantValueInstruction).getValue() = "0" and + instrTo.(CompareNEInstruction).hasOperands(opFrom, zero) + ) + } +} + +import Copied + +module TrackArrayConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { + exists(ArrayAllocation arrayAllocation | node = arrayAllocation.getNode()) + } + + predicate isSink(DataFlow::Node node) { + exists(PointerFormation pointerFormation | node = pointerFormation.getNode()) + } + + predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) + } +} + +module TrackArray = DataFlow::Global; + +predicate arrayIndexIsNegative( + DataFlow::Node arrayDeclarationNode, DataFlow::Node pointerFormationNode +) { + /* 1. Ensure the array access is reachable from the array declaration. */ + TrackArray::flow(arrayDeclarationNode, pointerFormationNode) and + /* 2. An offset cannot be negative. */ + exists(ArrayAllocation arrayAllocation, PointerFormation pointerFormation | + arrayDeclarationNode = arrayAllocation.getNode() and + pointerFormationNode = pointerFormation.getNode() + | + pointerFormation.getOffset() < 0 + ) +} + +predicate arrayIndexExceedsBounds( + DataFlow::Node arrayDeclarationNode, DataFlow::Node pointerFormationNode, int pointerOffset, + int arrayLength +) { + /* 1. Ensure the array access is reachable from the array declaration. */ + TrackArray::flow(arrayDeclarationNode, pointerFormationNode) and + /* 2. The offset must be at most (number of elements) + 1 = (the declared length). */ + exists(ArrayAllocation arrayAllocation, PointerFormation pointerFormation | + arrayDeclarationNode = arrayAllocation.getNode() and + pointerFormationNode = pointerFormation.getNode() and + pointerOffset = pointerFormation.getOffset() and + arrayLength = arrayAllocation.getLength() + | + arrayLength < pointerOffset + ) +} + +import TrackArray::PathGraph + +from TrackArray::PathNode source, TrackArray::PathNode sink, string message +where + not isExcluded(sink.getNode().asExpr(), + Memory1Package::pointerArithmeticFormsAnInvalidPointerQuery()) and + ( + exists(int pointerOffset, int arrayLength | + arrayIndexExceedsBounds(source.getNode(), sink.getNode(), pointerOffset, arrayLength) and + message = + "This pointer has offset " + pointerOffset + + " when the minimum possible length of the object is " + arrayLength + "." + ) + or + arrayIndexIsNegative(source.getNode(), sink.getNode()) and + message = "This pointer has a negative offset." + ) +select sink, source, sink, message diff --git a/cpp/misra/test/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.expected b/cpp/misra/test/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.expected new file mode 100644 index 000000000..2ec1a0ac6 --- /dev/null +++ b/cpp/misra/test/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.expected @@ -0,0 +1 @@ +No expected results have yet been specified \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.qlref b/cpp/misra/test/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.qlref new file mode 100644 index 000000000..049e02582 --- /dev/null +++ b/cpp/misra/test/rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.qlref @@ -0,0 +1 @@ +rules/RULE-8-7-1/PointerArgumentToCstringFunctionIsInvalid.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.expected b/cpp/misra/test/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.expected new file mode 100644 index 000000000..7cf6ed525 --- /dev/null +++ b/cpp/misra/test/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.expected @@ -0,0 +1,282 @@ +WARNING: unused method 'getAllocFunctionCall' (PointerArithmeticFormsAnInvalidPointer.ql:74,30-50) +edges +| test.cpp:3:65:3:69 | array | test.cpp:5:17:5:21 | array | provenance | | +| test.cpp:5:17:5:21 | array | test.cpp:6:17:6:25 | ... + ... | provenance | Config | +| test.cpp:5:17:5:21 | array | test.cpp:7:17:7:25 | ... + ... | provenance | Config | +| test.cpp:5:17:5:21 | array | test.cpp:9:7:9:15 | ... + ... | provenance | Config | +| test.cpp:5:17:5:21 | array | test.cpp:11:7:12:7 | ... + ... | provenance | Config | +| test.cpp:5:17:5:21 | array | test.cpp:13:19:13:27 | ... - ... | provenance | Config | +| test.cpp:16:59:16:63 | array | test.cpp:18:16:18:23 | access to array | provenance | Config | +| test.cpp:16:59:16:63 | array | test.cpp:19:16:19:23 | access to array | provenance | Config | +| test.cpp:16:59:16:63 | array | test.cpp:20:16:20:23 | access to array | provenance | Config | +| test.cpp:16:59:16:63 | array | test.cpp:21:16:21:23 | access to array | provenance | Config | +| test.cpp:16:59:16:63 | array | test.cpp:23:18:23:25 | access to array | provenance | Config | +| test.cpp:16:59:16:63 | array | test.cpp:25:18:25:26 | access to array | provenance | Config | +| test.cpp:28:56:28:60 | array | test.cpp:30:17:30:21 | array | provenance | | +| test.cpp:30:17:30:21 | array | test.cpp:31:17:31:25 | ... + ... | provenance | Config | +| test.cpp:30:17:30:21 | array | test.cpp:33:17:33:25 | ... + ... | provenance | Config | +| test.cpp:30:17:30:21 | array | test.cpp:35:17:35:25 | ... + ... | provenance | Config | +| test.cpp:30:17:30:21 | array | test.cpp:37:19:37:27 | ... + ... | provenance | Config | +| test.cpp:30:17:30:21 | array | test.cpp:39:19:39:27 | ... + ... | provenance | Config | +| test.cpp:30:17:30:21 | array | test.cpp:41:19:41:27 | ... - ... | provenance | Config | +| test.cpp:44:50:44:54 | array | test.cpp:47:7:47:14 | access to array | provenance | Config | +| test.cpp:44:50:44:54 | array | test.cpp:48:16:48:23 | access to array | provenance | Config | +| test.cpp:44:50:44:54 | array | test.cpp:51:16:51:23 | access to array | provenance | Config | +| test.cpp:44:50:44:54 | array | test.cpp:53:16:53:23 | access to array | provenance | Config | +| test.cpp:44:50:44:54 | array | test.cpp:55:18:55:25 | access to array | provenance | Config | +| test.cpp:44:50:44:54 | array | test.cpp:57:18:57:26 | access to array | provenance | Config | +| test.cpp:60:56:60:60 | array | test.cpp:62:17:62:21 | array | provenance | | +| test.cpp:62:17:62:21 | array | test.cpp:64:7:64:15 | ... + ... | provenance | Config | +| test.cpp:62:17:62:21 | array | test.cpp:65:17:65:25 | ... + ... | provenance | Config | +| test.cpp:62:17:62:21 | array | test.cpp:68:17:68:25 | ... + ... | provenance | Config | +| test.cpp:62:17:62:21 | array | test.cpp:70:19:70:27 | ... + ... | provenance | Config | +| test.cpp:62:17:62:21 | array | test.cpp:72:19:72:27 | ... - ... | provenance | Config | +| test.cpp:75:50:75:54 | array | test.cpp:77:16:77:23 | access to array | provenance | Config | +| test.cpp:75:50:75:54 | array | test.cpp:78:16:78:23 | access to array | provenance | Config | +| test.cpp:75:50:75:54 | array | test.cpp:79:16:79:23 | access to array | provenance | Config | +| test.cpp:75:50:75:54 | array | test.cpp:82:16:82:23 | access to array | provenance | Config | +| test.cpp:75:50:75:54 | array | test.cpp:84:18:84:25 | access to array | provenance | Config | +| test.cpp:75:50:75:54 | array | test.cpp:86:18:86:26 | access to array | provenance | Config | +| test.cpp:89:57:89:61 | array | test.cpp:91:17:91:21 | array | provenance | | +| test.cpp:91:17:91:21 | array | test.cpp:93:7:93:15 | ... + ... | provenance | Config | +| test.cpp:91:17:91:21 | array | test.cpp:95:7:95:15 | ... + ... | provenance | Config | +| test.cpp:91:17:91:21 | array | test.cpp:96:17:96:25 | ... + ... | provenance | Config | +| test.cpp:91:17:91:21 | array | test.cpp:98:19:98:27 | ... + ... | provenance | Config | +| test.cpp:91:17:91:21 | array | test.cpp:100:19:100:27 | ... - ... | provenance | Config | +| test.cpp:103:51:103:55 | array | test.cpp:106:7:106:14 | access to array | provenance | Config | +| test.cpp:103:51:103:55 | array | test.cpp:108:7:108:14 | access to array | provenance | Config | +| test.cpp:103:51:103:55 | array | test.cpp:110:7:110:14 | access to array | provenance | Config | +| test.cpp:103:51:103:55 | array | test.cpp:112:7:112:14 | access to array | provenance | Config | +| test.cpp:103:51:103:55 | array | test.cpp:114:18:114:25 | access to array | provenance | Config | +| test.cpp:103:51:103:55 | array | test.cpp:116:18:116:26 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:120:17:120:24 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:120:17:120:27 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:121:17:121:24 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:121:17:121:27 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:122:17:122:24 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:122:17:122:27 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:124:18:124:25 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:124:18:124:28 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:127:17:127:24 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:127:17:127:27 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:128:17:128:24 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:128:17:128:27 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:129:17:129:24 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:129:17:129:27 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:132:18:132:25 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:132:18:132:28 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:135:17:135:24 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:135:17:135:27 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:137:18:137:25 | access to array | provenance | Config | +| test.cpp:119:57:119:61 | array | test.cpp:137:18:137:28 | access to array | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:142:20:142:31 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:142:20:142:35 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:144:7:145:10 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:148:20:148:31 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:148:20:148:35 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:150:9:151:9 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:153:9:153:20 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:153:9:153:24 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:156:7:157:7 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:159:21:159:32 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:159:21:159:36 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:162:9:162:18 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:165:20:165:31 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:165:20:165:35 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:167:7:168:10 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:169:19:169:30 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:169:19:169:34 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:171:9:171:20 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:171:9:171:24 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:173:20:173:31 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:173:20:173:35 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:177:9:177:20 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:177:9:177:24 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:179:20:181:8 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:183:21:183:32 | * ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:183:21:183:36 | ... + ... | provenance | Config | +| test.cpp:141:63:141:67 | array | test.cpp:186:9:186:20 | * ... | provenance | Config | +| test.cpp:192:7:192:36 | definition of stack_single_dimensional_array | test.cpp:195:7:195:36 | stack_single_dimensional_array | provenance | | +| test.cpp:195:7:195:36 | stack_single_dimensional_array | test.cpp:3:65:3:69 | array | provenance | | +| test.cpp:195:7:195:36 | stack_single_dimensional_array | test.cpp:197:7:197:36 | stack_single_dimensional_array | provenance | | +| test.cpp:197:7:197:36 | stack_single_dimensional_array | test.cpp:16:59:16:63 | array | provenance | | +| test.cpp:215:7:215:57 | call to malloc | test.cpp:215:7:215:57 | call to malloc | provenance | | +| test.cpp:215:7:215:57 | call to malloc | test.cpp:220:7:220:37 | single_dimensional_array_malloc | provenance | | +| test.cpp:215:7:215:57 | call to malloc | test.cpp:220:7:220:37 | single_dimensional_array_malloc | provenance | Config | +| test.cpp:217:7:217:56 | call to calloc | test.cpp:217:7:217:56 | call to calloc | provenance | | +| test.cpp:217:7:217:56 | call to calloc | test.cpp:225:48:225:78 | single_dimensional_array_calloc | provenance | | +| test.cpp:219:43:220:77 | call to realloc | test.cpp:219:43:220:77 | call to realloc | provenance | | +| test.cpp:219:43:220:77 | call to realloc | test.cpp:229:7:229:38 | single_dimensional_array_realloc | provenance | | +| test.cpp:220:7:220:37 | single_dimensional_array_malloc | test.cpp:222:48:222:78 | single_dimensional_array_malloc | provenance | | +| test.cpp:222:48:222:78 | single_dimensional_array_malloc | test.cpp:28:56:28:60 | array | provenance | | +| test.cpp:222:48:222:78 | single_dimensional_array_malloc | test.cpp:223:42:223:72 | single_dimensional_array_malloc | provenance | | +| test.cpp:223:42:223:72 | single_dimensional_array_malloc | test.cpp:44:50:44:54 | array | provenance | | +| test.cpp:225:48:225:78 | single_dimensional_array_calloc | test.cpp:60:56:60:60 | array | provenance | | +| test.cpp:225:48:225:78 | single_dimensional_array_calloc | test.cpp:226:42:226:72 | single_dimensional_array_calloc | provenance | | +| test.cpp:226:42:226:72 | single_dimensional_array_calloc | test.cpp:75:50:75:54 | array | provenance | | +| test.cpp:229:7:229:38 | single_dimensional_array_realloc | test.cpp:89:57:89:61 | array | provenance | | +| test.cpp:229:7:229:38 | single_dimensional_array_realloc | test.cpp:230:43:230:74 | single_dimensional_array_realloc | provenance | | +| test.cpp:230:43:230:74 | single_dimensional_array_realloc | test.cpp:103:51:103:55 | array | provenance | | +| test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:239:50:239:78 | stack_multi_dimensional_array | provenance | | +| test.cpp:239:50:239:78 | stack_multi_dimensional_array | test.cpp:119:57:119:61 | array | provenance | | +| test.cpp:239:50:239:78 | stack_multi_dimensional_array | test.cpp:241:7:241:35 | stack_multi_dimensional_array | provenance | | +| test.cpp:241:7:241:35 | stack_multi_dimensional_array | test.cpp:141:63:141:67 | array | provenance | | +nodes +| test.cpp:3:65:3:69 | array | semmle.label | array | +| test.cpp:5:17:5:21 | array | semmle.label | array | +| test.cpp:6:17:6:25 | ... + ... | semmle.label | ... + ... | +| test.cpp:7:17:7:25 | ... + ... | semmle.label | ... + ... | +| test.cpp:9:7:9:15 | ... + ... | semmle.label | ... + ... | +| test.cpp:11:7:12:7 | ... + ... | semmle.label | ... + ... | +| test.cpp:13:19:13:27 | ... - ... | semmle.label | ... - ... | +| test.cpp:16:59:16:63 | array | semmle.label | array | +| test.cpp:18:16:18:23 | access to array | semmle.label | access to array | +| test.cpp:19:16:19:23 | access to array | semmle.label | access to array | +| test.cpp:20:16:20:23 | access to array | semmle.label | access to array | +| test.cpp:21:16:21:23 | access to array | semmle.label | access to array | +| test.cpp:23:18:23:25 | access to array | semmle.label | access to array | +| test.cpp:25:18:25:26 | access to array | semmle.label | access to array | +| test.cpp:28:56:28:60 | array | semmle.label | array | +| test.cpp:30:17:30:21 | array | semmle.label | array | +| test.cpp:31:17:31:25 | ... + ... | semmle.label | ... + ... | +| test.cpp:33:17:33:25 | ... + ... | semmle.label | ... + ... | +| test.cpp:35:17:35:25 | ... + ... | semmle.label | ... + ... | +| test.cpp:37:19:37:27 | ... + ... | semmle.label | ... + ... | +| test.cpp:39:19:39:27 | ... + ... | semmle.label | ... + ... | +| test.cpp:41:19:41:27 | ... - ... | semmle.label | ... - ... | +| test.cpp:44:50:44:54 | array | semmle.label | array | +| test.cpp:47:7:47:14 | access to array | semmle.label | access to array | +| test.cpp:48:16:48:23 | access to array | semmle.label | access to array | +| test.cpp:51:16:51:23 | access to array | semmle.label | access to array | +| test.cpp:53:16:53:23 | access to array | semmle.label | access to array | +| test.cpp:55:18:55:25 | access to array | semmle.label | access to array | +| test.cpp:57:18:57:26 | access to array | semmle.label | access to array | +| test.cpp:60:56:60:60 | array | semmle.label | array | +| test.cpp:62:17:62:21 | array | semmle.label | array | +| test.cpp:64:7:64:15 | ... + ... | semmle.label | ... + ... | +| test.cpp:65:17:65:25 | ... + ... | semmle.label | ... + ... | +| test.cpp:68:17:68:25 | ... + ... | semmle.label | ... + ... | +| test.cpp:70:19:70:27 | ... + ... | semmle.label | ... + ... | +| test.cpp:72:19:72:27 | ... - ... | semmle.label | ... - ... | +| test.cpp:75:50:75:54 | array | semmle.label | array | +| test.cpp:77:16:77:23 | access to array | semmle.label | access to array | +| test.cpp:78:16:78:23 | access to array | semmle.label | access to array | +| test.cpp:79:16:79:23 | access to array | semmle.label | access to array | +| test.cpp:82:16:82:23 | access to array | semmle.label | access to array | +| test.cpp:84:18:84:25 | access to array | semmle.label | access to array | +| test.cpp:86:18:86:26 | access to array | semmle.label | access to array | +| test.cpp:89:57:89:61 | array | semmle.label | array | +| test.cpp:91:17:91:21 | array | semmle.label | array | +| test.cpp:93:7:93:15 | ... + ... | semmle.label | ... + ... | +| test.cpp:95:7:95:15 | ... + ... | semmle.label | ... + ... | +| test.cpp:96:17:96:25 | ... + ... | semmle.label | ... + ... | +| test.cpp:98:19:98:27 | ... + ... | semmle.label | ... + ... | +| test.cpp:100:19:100:27 | ... - ... | semmle.label | ... - ... | +| test.cpp:103:51:103:55 | array | semmle.label | array | +| test.cpp:106:7:106:14 | access to array | semmle.label | access to array | +| test.cpp:108:7:108:14 | access to array | semmle.label | access to array | +| test.cpp:110:7:110:14 | access to array | semmle.label | access to array | +| test.cpp:112:7:112:14 | access to array | semmle.label | access to array | +| test.cpp:114:18:114:25 | access to array | semmle.label | access to array | +| test.cpp:116:18:116:26 | access to array | semmle.label | access to array | +| test.cpp:119:57:119:61 | array | semmle.label | array | +| test.cpp:120:17:120:24 | access to array | semmle.label | access to array | +| test.cpp:120:17:120:27 | access to array | semmle.label | access to array | +| test.cpp:121:17:121:24 | access to array | semmle.label | access to array | +| test.cpp:121:17:121:27 | access to array | semmle.label | access to array | +| test.cpp:122:17:122:24 | access to array | semmle.label | access to array | +| test.cpp:122:17:122:27 | access to array | semmle.label | access to array | +| test.cpp:124:18:124:25 | access to array | semmle.label | access to array | +| test.cpp:124:18:124:28 | access to array | semmle.label | access to array | +| test.cpp:127:17:127:24 | access to array | semmle.label | access to array | +| test.cpp:127:17:127:27 | access to array | semmle.label | access to array | +| test.cpp:128:17:128:24 | access to array | semmle.label | access to array | +| test.cpp:128:17:128:27 | access to array | semmle.label | access to array | +| test.cpp:129:17:129:24 | access to array | semmle.label | access to array | +| test.cpp:129:17:129:27 | access to array | semmle.label | access to array | +| test.cpp:132:18:132:25 | access to array | semmle.label | access to array | +| test.cpp:132:18:132:28 | access to array | semmle.label | access to array | +| test.cpp:135:17:135:24 | access to array | semmle.label | access to array | +| test.cpp:135:17:135:27 | access to array | semmle.label | access to array | +| test.cpp:137:18:137:25 | access to array | semmle.label | access to array | +| test.cpp:137:18:137:28 | access to array | semmle.label | access to array | +| test.cpp:141:63:141:67 | array | semmle.label | array | +| test.cpp:142:20:142:31 | * ... | semmle.label | * ... | +| test.cpp:142:20:142:35 | ... + ... | semmle.label | ... + ... | +| test.cpp:144:7:145:10 | * ... | semmle.label | * ... | +| test.cpp:148:20:148:31 | * ... | semmle.label | * ... | +| test.cpp:148:20:148:35 | ... + ... | semmle.label | ... + ... | +| test.cpp:150:9:151:9 | ... + ... | semmle.label | ... + ... | +| test.cpp:153:9:153:20 | * ... | semmle.label | * ... | +| test.cpp:153:9:153:24 | ... + ... | semmle.label | ... + ... | +| test.cpp:156:7:157:7 | ... + ... | semmle.label | ... + ... | +| test.cpp:159:21:159:32 | * ... | semmle.label | * ... | +| test.cpp:159:21:159:36 | ... + ... | semmle.label | ... + ... | +| test.cpp:162:9:162:18 | ... + ... | semmle.label | ... + ... | +| test.cpp:165:20:165:31 | * ... | semmle.label | * ... | +| test.cpp:165:20:165:35 | ... + ... | semmle.label | ... + ... | +| test.cpp:167:7:168:10 | * ... | semmle.label | * ... | +| test.cpp:169:19:169:30 | * ... | semmle.label | * ... | +| test.cpp:169:19:169:34 | ... + ... | semmle.label | ... + ... | +| test.cpp:171:9:171:20 | * ... | semmle.label | * ... | +| test.cpp:171:9:171:24 | ... + ... | semmle.label | ... + ... | +| test.cpp:173:20:173:31 | * ... | semmle.label | * ... | +| test.cpp:173:20:173:35 | ... + ... | semmle.label | ... + ... | +| test.cpp:177:9:177:20 | * ... | semmle.label | * ... | +| test.cpp:177:9:177:24 | ... + ... | semmle.label | ... + ... | +| test.cpp:179:20:181:8 | * ... | semmle.label | * ... | +| test.cpp:183:21:183:32 | * ... | semmle.label | * ... | +| test.cpp:183:21:183:36 | ... + ... | semmle.label | ... + ... | +| test.cpp:186:9:186:20 | * ... | semmle.label | * ... | +| test.cpp:192:7:192:36 | definition of stack_single_dimensional_array | semmle.label | definition of stack_single_dimensional_array | +| test.cpp:195:7:195:36 | stack_single_dimensional_array | semmle.label | stack_single_dimensional_array | +| test.cpp:197:7:197:36 | stack_single_dimensional_array | semmle.label | stack_single_dimensional_array | +| test.cpp:215:7:215:57 | call to malloc | semmle.label | call to malloc | +| test.cpp:215:7:215:57 | call to malloc | semmle.label | call to malloc | +| test.cpp:217:7:217:56 | call to calloc | semmle.label | call to calloc | +| test.cpp:217:7:217:56 | call to calloc | semmle.label | call to calloc | +| test.cpp:219:43:220:77 | call to realloc | semmle.label | call to realloc | +| test.cpp:219:43:220:77 | call to realloc | semmle.label | call to realloc | +| test.cpp:220:7:220:37 | single_dimensional_array_malloc | semmle.label | single_dimensional_array_malloc | +| test.cpp:222:48:222:78 | single_dimensional_array_malloc | semmle.label | single_dimensional_array_malloc | +| test.cpp:223:42:223:72 | single_dimensional_array_malloc | semmle.label | single_dimensional_array_malloc | +| test.cpp:225:48:225:78 | single_dimensional_array_calloc | semmle.label | single_dimensional_array_calloc | +| test.cpp:226:42:226:72 | single_dimensional_array_calloc | semmle.label | single_dimensional_array_calloc | +| test.cpp:229:7:229:38 | single_dimensional_array_realloc | semmle.label | single_dimensional_array_realloc | +| test.cpp:230:43:230:74 | single_dimensional_array_realloc | semmle.label | single_dimensional_array_realloc | +| test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | semmle.label | definition of stack_multi_dimensional_array | +| test.cpp:239:50:239:78 | stack_multi_dimensional_array | semmle.label | stack_multi_dimensional_array | +| test.cpp:241:7:241:35 | stack_multi_dimensional_array | semmle.label | stack_multi_dimensional_array | +subpaths +#select +| test.cpp:11:7:12:7 | ... + ... | test.cpp:192:7:192:36 | definition of stack_single_dimensional_array | test.cpp:11:7:12:7 | ... + ... | This pointer has offset 4 when the minimum possible length of the object is 3. | +| test.cpp:13:19:13:27 | ... - ... | test.cpp:192:7:192:36 | definition of stack_single_dimensional_array | test.cpp:13:19:13:27 | ... - ... | This pointer has a negative offset. | +| test.cpp:23:18:23:25 | access to array | test.cpp:192:7:192:36 | definition of stack_single_dimensional_array | test.cpp:23:18:23:25 | access to array | This pointer has offset 4 when the minimum possible length of the object is 3. | +| test.cpp:25:18:25:26 | access to array | test.cpp:192:7:192:36 | definition of stack_single_dimensional_array | test.cpp:25:18:25:26 | access to array | This pointer has a negative offset. | +| test.cpp:33:17:33:25 | ... + ... | test.cpp:215:7:215:57 | call to malloc | test.cpp:33:17:33:25 | ... + ... | This pointer has offset 2 when the minimum possible length of the object is 1. | +| test.cpp:35:17:35:25 | ... + ... | test.cpp:215:7:215:57 | call to malloc | test.cpp:35:17:35:25 | ... + ... | This pointer has offset 3 when the minimum possible length of the object is 1. | +| test.cpp:37:19:37:27 | ... + ... | test.cpp:215:7:215:57 | call to malloc | test.cpp:37:19:37:27 | ... + ... | This pointer has offset 4 when the minimum possible length of the object is 1. | +| test.cpp:39:19:39:27 | ... + ... | test.cpp:215:7:215:57 | call to malloc | test.cpp:39:19:39:27 | ... + ... | This pointer has offset 5 when the minimum possible length of the object is 1. | +| test.cpp:41:19:41:27 | ... - ... | test.cpp:215:7:215:57 | call to malloc | test.cpp:41:19:41:27 | ... - ... | This pointer has a negative offset. | +| test.cpp:51:16:51:23 | access to array | test.cpp:215:7:215:57 | call to malloc | test.cpp:51:16:51:23 | access to array | This pointer has offset 2 when the minimum possible length of the object is 1. | +| test.cpp:53:16:53:23 | access to array | test.cpp:215:7:215:57 | call to malloc | test.cpp:53:16:53:23 | access to array | This pointer has offset 3 when the minimum possible length of the object is 1. | +| test.cpp:55:18:55:25 | access to array | test.cpp:215:7:215:57 | call to malloc | test.cpp:55:18:55:25 | access to array | This pointer has offset 4 when the minimum possible length of the object is 1. | +| test.cpp:57:18:57:26 | access to array | test.cpp:215:7:215:57 | call to malloc | test.cpp:57:18:57:26 | access to array | This pointer has a negative offset. | +| test.cpp:68:17:68:25 | ... + ... | test.cpp:217:7:217:56 | call to calloc | test.cpp:68:17:68:25 | ... + ... | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:70:19:70:27 | ... + ... | test.cpp:217:7:217:56 | call to calloc | test.cpp:70:19:70:27 | ... + ... | This pointer has offset 4 when the minimum possible length of the object is 2. | +| test.cpp:72:19:72:27 | ... - ... | test.cpp:217:7:217:56 | call to calloc | test.cpp:72:19:72:27 | ... - ... | This pointer has a negative offset. | +| test.cpp:82:16:82:23 | access to array | test.cpp:217:7:217:56 | call to calloc | test.cpp:82:16:82:23 | access to array | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:84:18:84:25 | access to array | test.cpp:217:7:217:56 | call to calloc | test.cpp:84:18:84:25 | access to array | This pointer has offset 4 when the minimum possible length of the object is 2. | +| test.cpp:86:18:86:26 | access to array | test.cpp:217:7:217:56 | call to calloc | test.cpp:86:18:86:26 | access to array | This pointer has a negative offset. | +| test.cpp:98:19:98:27 | ... + ... | test.cpp:219:43:220:77 | call to realloc | test.cpp:98:19:98:27 | ... + ... | This pointer has offset 4 when the minimum possible length of the object is 3. | +| test.cpp:100:19:100:27 | ... - ... | test.cpp:219:43:220:77 | call to realloc | test.cpp:100:19:100:27 | ... - ... | This pointer has a negative offset. | +| test.cpp:114:18:114:25 | access to array | test.cpp:219:43:220:77 | call to realloc | test.cpp:114:18:114:25 | access to array | This pointer has offset 4 when the minimum possible length of the object is 3. | +| test.cpp:116:18:116:26 | access to array | test.cpp:219:43:220:77 | call to realloc | test.cpp:116:18:116:26 | access to array | This pointer has a negative offset. | +| test.cpp:124:18:124:28 | access to array | test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:124:18:124:28 | access to array | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:132:18:132:28 | access to array | test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:132:18:132:28 | access to array | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:137:18:137:25 | access to array | test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:137:18:137:25 | access to array | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:159:21:159:36 | ... + ... | test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:159:21:159:36 | ... + ... | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:162:9:162:18 | ... + ... | test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:162:9:162:18 | ... + ... | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:173:20:173:35 | ... + ... | test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:173:20:173:35 | ... + ... | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:183:21:183:32 | * ... | test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:183:21:183:32 | * ... | This pointer has offset 3 when the minimum possible length of the object is 2. | +| test.cpp:186:9:186:20 | * ... | test.cpp:233:7:233:35 | definition of stack_multi_dimensional_array | test.cpp:186:9:186:20 | * ... | This pointer has offset 3 when the minimum possible length of the object is 2. | diff --git a/cpp/misra/test/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.qlref b/cpp/misra/test/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.qlref new file mode 100644 index 000000000..a512fe0a6 --- /dev/null +++ b/cpp/misra/test/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.qlref @@ -0,0 +1 @@ +rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-8-7-1/test.cpp b/cpp/misra/test/rules/RULE-8-7-1/test.cpp new file mode 100644 index 000000000..793607879 --- /dev/null +++ b/cpp/misra/test/rules/RULE-8-7-1/test.cpp @@ -0,0 +1,244 @@ +#include + +void stack_allocated_single_dimensional_pointer_arithmetic(int *array) { + /* 1. Pointer formed from performing arithmetic */ + int *valid1 = array; // COMPLIANT: pointer is within boundary + int *valid2 = array + 1; // COMPLIANT: pointer is within boundary + int *valid3 = array + 2; // COMPLIANT: pointer is within boundary + int *valid4 = + array + 3; // COMPLIANT: pointer points one beyond the last element + int *invalid1 = + array + + 4; // NON_COMPLIANT: pointer points more than one beyond the last element + int *invalid2 = array - 1; // NON_COMPLIANT: pointer is outside boundary +} + +void stack_allocated_single_dimensional_array_access(int *array) { + /* 2. Array Access (entails pointer arithmetic) */ + int valid1 = array[0]; // COMPLIANT: pointer is within boundary + int valid2 = array[1]; // COMPLIANT: pointer is within boundary + int valid3 = array[2]; // COMPLIANT: pointer is within boundary + int valid4 = array[3]; // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 + int invalid1 = array[4]; // NON_COMPLIANT: pointer points more than one beyond + // the last element + int invalid2 = array[-1]; // NON_COMPLIANT: pointer is outside boundary +} + +void malloc_single_dimensional_pointer_arithmetic(int *array) { // [1, 4] + /* 1. Pointer formed from performing arithmetic */ + int *valid1 = array; // COMPLIANT: pointer is within boundary (lower bound: 1) + int *valid2 = array + 1; // COMPLIANT: pointer points more than one beyond the + // last element (lower bound: 1) + int *valid3 = array + 2; // NON_COMPLIANT: pointer points more than one beyond + // the last element (lower bound: 1) + int *valid4 = array + 3; // NON_COMPLIANT: pointer points more than one beyond + // the last element (lower bound: 1) + int *invalid1 = array + 4; // NON_COMPLIANT: pointer points more than one + // beyond the last element (lower bound: 1) + int *invalid2 = array + 5; // NON_COMPLIANT: pointer points more than one + // beyond the last element (lower bound: 1) + int *invalid3 = array - 1; // NON_COMPLIANT: pointer is outside boundary +} + +void malloc_single_dimensional_array_access(int *array) { // [1, 4] + /* 2. Array Access (entails pointer arithmetic) */ + int valid1 = + array[0]; // COMPLIANT: pointer is within boundary (lower bound: 1) + int valid2 = array[1]; // COMPLIANT: pointer points more than one beyond the + // last element, but non-compliant to Rule 4.1.3 (lower + // bound: 1) + int valid3 = array[2]; // NON_COMPLIANT: pointer points more than one beyond + // the last element (lower bound: 1) + int valid4 = array[3]; // NON_COMPLIANT: pointer points more than one beyond + // the last element (lower bound: 1) + int invalid1 = array[4]; // NON_COMPLIANT: pointer points more than one beyond + // the last element (lower bound: 1) + int invalid2 = array[-1]; // NON_COMPLIANT: pointer is outside boundary +} + +void calloc_single_dimensional_pointer_arithmetic(int *array) { // [2, 5] + /* 1. Pointer formed from performing arithmetic */ + int *valid1 = array; // COMPLIANT: pointer is within boundary (lower bound: 2) + int *valid2 = + array + 1; // COMPLIANT: pointer is within boundary (lower bound: 2) + int *valid3 = array + 2; // COMPLIANT: pointer points more than one beyond the + // last element, but non-compliant to Rule 4.1.3 + // (lower bound: 2) + int *valid4 = array + 3; // NON_COMPLIANT: pointer points more than one beyond + // the last element (lower bound: 2) + int *invalid1 = array + 4; // NON_COMPLIANT: pointer points more than one + // beyond the last element (lower bound: 2) + int *invalid2 = array - 1; // NON_COMPLIANT: pointer is outside boundary +} + +void calloc_single_dimensional_array_access(int *array) { // [2, 5] + /* 2. Array Access (entails pointer arithmetic) */ + int valid1 = array[0]; // COMPLIANT: pointer is within boundary + int valid2 = array[1]; // COMPLIANT: pointer is within boundary + int valid3 = array[2]; // COMPLIANT: pointer points more than one beyond the + // last element, but non-compliant to Rule 4.1.3 + // (lower bound: 2) + int valid4 = array[3]; // NON_COMPLIANT: pointer points more than one beyond + // the last element (lower bound: 2) + int invalid1 = array[4]; // NON_COMPLIANT: pointer points more than one + // beyond the last element (lower bound: 2) + int invalid2 = array[-1]; // NON_COMPLIANT: pointer is outside boundary +} + +void realloc_single_dimensional_pointer_arithmetic(int *array) { // [3, 6] + /* 1. Pointer formed from performing arithmetic */ + int *valid1 = array; // COMPLIANT: pointer is within boundary (lower bound: 3) + int *valid2 = + array + 1; // COMPLIANT: pointer is within boundary (lower bound: 3) + int *valid3 = + array + 2; // COMPLIANT: pointer is within boundary (lower bound: 3) + int *valid4 = array + 3; // COMPLIANT: pointer points one beyond the last + // element (lower bound: 3) + int *invalid1 = array + 4; // NON_COMPLIANT: pointer points more than one + // beyond the last element (lower bound: 3) + int *invalid2 = array - 1; // NON_COMPLIANT: pointer is outside boundary +} + +void realloc_single_dimensional_array_access(int *array) { // [3, 6] + /* 2. Array Access (entails pointer arithmetic) */ + int valid1 = + array[0]; // COMPLIANT: pointer is within boundary (lower bound: 3) + int valid2 = + array[1]; // COMPLIANT: pointer is within boundary (lower bound: 3) + int valid3 = + array[2]; // COMPLIANT: pointer is within boundary (lower bound: 3) + int valid4 = + array[3]; // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 (lower bound: 3) + int invalid1 = array[4]; // NON_COMPLIANT: pointer points more than one beyond + // the last element (lower bound: 3) + int invalid2 = array[-1]; // NON_COMPLIANT: pointer is outside boundary +} + +void stack_allocated_multi_dimensional_array_access(int array[2][3]) { + int valid11 = array[0][0]; // COMPLIANT: pointer is within boundary + int valid12 = array[0][1]; // COMPLIANT: pointer is within boundary + int valid13 = array[0][2]; // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 + int invalid1 = array[0][3]; // NON_COMPLIANT: pointer points more than one + // beyond the last element + + int valid21 = array[1][0]; // COMPLIANT: pointer is within boundary + int valid22 = array[1][1]; // COMPLIANT: pointer is within boundary + int valid23 = array[1][2]; // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 + + int invalid2 = array[1][3]; // NON_COMPLIANT: pointer points more than one + // beyond the last element + + int valid31 = array[2][0]; // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 + int invalid3 = array[3][0]; // NON_COMPLIANT: pointer points more than one + // beyond the last element +} + +void stack_allocated_multi_dimensional_pointer_arithmetic(int array[2][3]) { + int valid111 = *(*(array + 0) + 0); // COMPLIANT: pointer is within boundary + int valid112 = *( + *(array + + 0)); // COMPLIANT: pointer is within boundary (equivalent to the above) + int valid113 = **array; // COMPLIANT: pointer is within boundary (equivalent + // to the above) + int valid121 = *(*(array + 0) + 1); // COMPLIANT: pointer is within boundary + int valid122 = + *(*array + + 1); // COMPLIANT: pointer is within boundary (equivalent to the above) + int valid131 = + *(*(array + 0) + 2); // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 + int valid132 = *( + *array + + 2); // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 (equivalent to the above) + int invalid11 = *(*(array + 0) + 3); // NON_COMPLIANT: pointer points more + // than one beyond the last element + int invalid12 = + *(*array + 3); // NON_COMPLIANT: pointer points more than + // one beyond the last element (equivalent to the above) + + int valid211 = *(*(array + 1) + 0); // COMPLIANT: pointer is within boundary + int valid212 = *( + *(array + + 1)); // COMPLIANT: pointer is within boundary (equivalent to the above) + int valid22 = *(*(array + 1) + 1); // COMPLIANT: pointer is within boundary + int valid23 = + *(*(array + 1) + 2); // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 + int invalid2 = *(*(array + 1) + 3); // NON_COMPLIANT: pointer points more than + // one beyond the last element + + int valid311 = + *(*(array + 2) + 0); // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 + int valid312 = *(*( + array + + 2)); // COMPLIANT: pointer points one beyond the last + // element, but non-compliant to Rule 4.1.3 (equivalent to the above) + int invalid31 = *(*(array + 3) + 0); // NON_COMPLIANT: pointer points more + // than one beyond the last element + int invalid32 = + *(*(array + 3)); // NON_COMPLIANT: pointer points more than + // one beyond the last element (equivalent to the above) +} + +int main(int argc, char *argv[]) { + /* 1. Single-dimensional array initialized on the stack */ + int stack_single_dimensional_array[3] = {0, 1, 2}; + + stack_allocated_single_dimensional_pointer_arithmetic( + stack_single_dimensional_array); + stack_allocated_single_dimensional_array_access( + stack_single_dimensional_array); + + /* 2. Single-dimensional array initialized on the heap */ + int num_of_elements_malloc; + int num_of_elements_calloc; + int num_of_elements_realloc; + + if (argc) { + num_of_elements_malloc = 1; + num_of_elements_calloc = 2; + num_of_elements_realloc = 3; + } else { + num_of_elements_malloc = 4; + num_of_elements_calloc = 5; + num_of_elements_realloc = 6; + } + + int *single_dimensional_array_malloc = + (int *)malloc(num_of_elements_malloc * sizeof(int)); + int *single_dimensional_array_calloc = + (int *)calloc(num_of_elements_calloc, sizeof(int)); + + int *single_dimensional_array_realloc = (int *)realloc( + single_dimensional_array_malloc, num_of_elements_realloc * sizeof(int)); + + malloc_single_dimensional_pointer_arithmetic(single_dimensional_array_malloc); + malloc_single_dimensional_array_access(single_dimensional_array_malloc); + + calloc_single_dimensional_pointer_arithmetic(single_dimensional_array_calloc); + calloc_single_dimensional_array_access(single_dimensional_array_calloc); + + realloc_single_dimensional_pointer_arithmetic( + single_dimensional_array_realloc); + realloc_single_dimensional_array_access(single_dimensional_array_realloc); + + /* 3. Multi-dimensional array initialized on the stack */ + int stack_multi_dimensional_array[2][3] = {{1, 2, 3}, {4, 5, 6}}; + + /* 4. Multi-dimensional array initialized on the heap */ + int (*heap_multi_dimensional_array)[3] = + (int (*)[3])malloc(sizeof(int[2][3])); + + stack_allocated_multi_dimensional_array_access(stack_multi_dimensional_array); + stack_allocated_multi_dimensional_pointer_arithmetic( + stack_multi_dimensional_array); + + return 0; +} diff --git a/rule_packages/cpp/Memory1.json b/rule_packages/cpp/Memory1.json new file mode 100644 index 000000000..b8c5005ca --- /dev/null +++ b/rule_packages/cpp/Memory1.json @@ -0,0 +1,35 @@ +{ + "MISRA-C++-2023": { + "RULE-8-7-1": { + "properties": { + "enforcement": "undecidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Pointers obtained as result of performing arithmetic should point to an initialized object, or an element right next to the last element of an array.", + "kind": "problem", + "name": "Pointer arithmetic shall not form an invalid pointer.", + "precision": "high", + "severity": "error", + "short_name": "PointerArithmeticFormsAnInvalidPointer", + "tags": [ + "scope/system" + ] + }, + { + "description": "Pointer and index arguments passed to functions in should result in valid reads and/or writes.", + "kind": "problem", + "name": "Pointer and index arguments passed to functions in shall not be invalid.", + "precision": "high", + "severity": "error", + "short_name": "PointerArgumentToCstringFunctionIsInvalid", + "tags": [ + "scope/system" + ] + } + ], + "title": "Pointers obtained as result of performing arithmetic should point to an initialized object, or an element right next to the last element of an array." + } + } +} diff --git a/rule_packages/cpp/Memory2.json b/rule_packages/cpp/Memory2.json new file mode 100644 index 000000000..067af41b1 --- /dev/null +++ b/rule_packages/cpp/Memory2.json @@ -0,0 +1,24 @@ +{ + "MISRA-C++-2023": { + "RULE-8-7-2": { + "properties": { + "enforcement": "undecidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Pointer difference should be taken from pointers that belong to a same array.", + "kind": "problem", + "name": "Subtraction between pointers shall only be applied to ones that address elements of the same array.", + "precision": "very-high", + "severity": "error", + "short_name": "PointerDifferenceTakenBetweenDifferentArrays", + "tags": [ + "scope/system" + ] + } + ], + "title": "Pointer difference should be taken from pointers that belong to a same array." + } + } +} diff --git a/rule_packages/cpp/Memory3.json b/rule_packages/cpp/Memory3.json new file mode 100644 index 000000000..1117c552b --- /dev/null +++ b/rule_packages/cpp/Memory3.json @@ -0,0 +1,24 @@ +{ + "MISRA-C++-2023": { + "RULE-8-9-1": { + "properties": { + "enforcement": "undecidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Pointer comparison should be done between ones that belong to a same array.", + "kind": "problem", + "name": "The built-in relational operators >, >=, < and <= shall not be applied to objects of pointer type.", + "precision": "very-high", + "severity": "error", + "short_name": "PointerComparedBetweenDifferentArrays", + "tags": [ + "scope/system" + ] + } + ], + "title": "Pointer comparison should be done between ones that belong to a same array." + } + } +} diff --git a/rule_packages/cpp/Memory4.json b/rule_packages/cpp/Memory4.json new file mode 100644 index 000000000..f2fa1803c --- /dev/null +++ b/rule_packages/cpp/Memory4.json @@ -0,0 +1,24 @@ +{ + "MISRA-C++-2023": { + "RULE-8-18-1": { + "properties": { + "enforcement": "undecidable", + "obligation": "mandatory" + }, + "queries": [ + { + "description": "Copying a member of a union to another, and copying a slice of an array to an overlapping one causes undefined behavior.", + "kind": "problem", + "name": "An object or subobject must not be copied to an overlapping object.", + "precision": "high", + "severity": "error", + "short_name": "ObjectMustNotBeCopiedToAnOverlappingObject", + "tags": [ + "scope/system" + ] + } + ], + "title": "Copying a member of a union to another, and copying a slice of an array to an overlapping one causes undefined behavior." + } + } +} diff --git a/rule_packages/cpp/Memory5.json b/rule_packages/cpp/Memory5.json new file mode 100644 index 000000000..40a5ea765 --- /dev/null +++ b/rule_packages/cpp/Memory5.json @@ -0,0 +1,24 @@ +{ + "MISRA-C++-2023": { + "RULE-21-6-2": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Dynamically allocated memory must not be managed manually.", + "kind": "problem", + "name": "Dynamic memory shall be managed automatically.", + "precision": "very-high", + "severity": "error", + "short_name": "DynamicMemoryManagedManually", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "Dynamically allocated memory must not be managed manually." + } + } +} diff --git a/rule_packages/cpp/Memory6.json b/rule_packages/cpp/Memory6.json new file mode 100644 index 000000000..14a935afb --- /dev/null +++ b/rule_packages/cpp/Memory6.json @@ -0,0 +1,24 @@ +{ + "MISRA-C++-2023": { + "RULE-21-6-3": { + "properties": { + "enforcement": "decidable", + "obligation": "required" + }, + "queries": [ + { + "description": "Using advanced memory management that either alters allocation and deallocation or constructs object construction on uninitalized memory may result in undefined behavior.", + "kind": "problem", + "name": "Advanced memory management shall not be used.", + "precision": "very-high", + "severity": "error", + "short_name": "AdvancedMemoryManagementUsed", + "tags": [ + "scope/single-translation-unit" + ] + } + ], + "title": "Using advanced memory management that either alters allocation and deallocation or constructs object construction on uninitalized memory may result in undefined behavior." + } + } +} diff --git a/rules.csv b/rules.csv index a2eb7eddd..1a2112b45 100644 --- a/rules.csv +++ b/rules.csv @@ -895,11 +895,11 @@ cpp,MISRA-C++-2023,RULE-8-2-10,Yes,Required,Undecidable,System,"Functions shall cpp,MISRA-C++-2023,RULE-8-2-11,Yes,Required,Decidable,Single Translation Unit,An argument passed via ellipsis shall have an appropriate type,,Preconditions,Easy, cpp,MISRA-C++-2023,RULE-8-3-1,Yes,Advisory,Decidable,Single Translation Unit,The built-in unary - operator should not be applied to an expression of unsigned type,M5-3-2,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-8-3-2,Yes,Advisory,Decidable,Single Translation Unit,The built-in unary + operator should not be used,,Banned,Easy, -cpp,MISRA-C++-2023,RULE-8-7-1,Yes,Required,Undecidable,System,Pointer arithmetic shall not form an invalid pointer,ARR30-C,Memory,Easy, -cpp,MISRA-C++-2023,RULE-8-7-2,Yes,Required,Undecidable,System,Subtraction between pointers shall only be applied to pointers that address elements of the same array,ARR36-C,Memory,Easy, -cpp,MISRA-C++-2023,RULE-8-9-1,Yes,Required,Undecidable,System,"The built-in relational operators >, >=, < and <= shall not be applied to objects of pointer type, except where they point to elements of the same array",ARR36-C,Memory,Easy, +cpp,MISRA-C++-2023,RULE-8-7-1,Yes,Required,Undecidable,System,Pointer arithmetic shall not form an invalid pointer,ARR30-C,Memory1,Easy, +cpp,MISRA-C++-2023,RULE-8-7-2,Yes,Required,Undecidable,System,Subtraction between pointers shall only be applied to pointers that address elements of the same array,ARR36-C,Memory2,Easy, +cpp,MISRA-C++-2023,RULE-8-9-1,Yes,Required,Undecidable,System,"The built-in relational operators >, >=, < and <= shall not be applied to objects of pointer type, except where they point to elements of the same array",ARR36-C,Memory3,Easy, cpp,MISRA-C++-2023,RULE-8-14-1,Yes,Advisory,Undecidable,System,The right-hand operand of a logical && or operator should not contain persistent side effects,"M5-14-1, RULE-13-5",SideEffects3,Medium, -cpp,MISRA-C++-2023,RULE-8-18-1,Yes,Mandatory,Undecidable,System,An object or subobject must not be copied to an overlapping object,"M0-2-1, RULE-19-1",Memory,Hard, +cpp,MISRA-C++-2023,RULE-8-18-1,Yes,Mandatory,Undecidable,System,An object or subobject must not be copied to an overlapping object,"M0-2-1, RULE-19-1",Memory4,Hard, cpp,MISRA-C++-2023,RULE-8-18-2,Yes,Advisory,Decidable,Single Translation Unit,The result of an assignment operator should not be used,RULE-13-4,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-8-19-1,Yes,Advisory,Decidable,Single Translation Unit,The comma operator should not be used,M5-18-1,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-8-20-1,Yes,Advisory,Decidable,Single Translation Unit,An unsigned arithmetic operation with constant operands should not wrap,INT30-C,ImportMisra23,Import, @@ -979,8 +979,8 @@ cpp,MISRA-C++-2023,RULE-21-2-2,Yes,Required,Decidable,Single Translation Unit,"T cpp,MISRA-C++-2023,RULE-21-2-3,Yes,Required,Decidable,Single Translation Unit,The library function system from shall not be used,M18-0-3,BannedAPIs,Easy, cpp,MISRA-C++-2023,RULE-21-2-4,Yes,Required,Decidable,Single Translation Unit,The macro offsetof shall not be used,M18-2-1,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-21-6-1,Yes,Advisory,Undecidable,Single Translation Unit,Dynamic memory should not be used,DIR-4-12,Banned,Easy, -cpp,MISRA-C++-2023,RULE-21-6-2,Yes,Required,Decidable,Single Translation Unit,Dynamic memory shall be managed automatically,,Memory,Easy, -cpp,MISRA-C++-2023,RULE-21-6-3,Yes,Required,Decidable,Single Translation Unit,Advanced memory management shall not be used,,Memory,Medium, +cpp,MISRA-C++-2023,RULE-21-6-2,Yes,Required,Decidable,Single Translation Unit,Dynamic memory shall be managed automatically,,Memory5,Easy, +cpp,MISRA-C++-2023,RULE-21-6-3,Yes,Required,Decidable,Single Translation Unit,Advanced memory management shall not be used,,Memory6,Medium, cpp,MISRA-C++-2023,RULE-21-6-4,Yes,Required,Decidable,System,"If a project defines either a sized or unsized version of a global operator delete, then both shall be defined",A18-5-4,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-21-6-5,Yes,Required,Decidable,Single Translation Unit,A pointer to an incomplete class type shall not be deleted,A5-3-3,ImportMisra23,Import, cpp,MISRA-C++-2023,RULE-21-10-1,Yes,Required,Decidable,Single Translation Unit,The features of shall not be used,DCL50-CPP,BannedAPIs,Easy,