diff --git a/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.md b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.md new file mode 100644 index 0000000000..b79d9f2f97 --- /dev/null +++ b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.md @@ -0,0 +1,192 @@ +# ARR39-C: Do not add or subtract a scaled integer to a pointer + +This query implements the CERT-C rule ARR39-C: + +> Do not add or subtract a scaled integer to a pointer + + +## Description + +Pointer arithmetic is appropriate only when the pointer argument refers to an array (see [ARR37-C. Do not add or subtract an integer to a pointer to a non-array object](https://wiki.sei.cmu.edu/confluence/display/c/ARR37-C.+Do+not+add+or+subtract+an+integer+to+a+pointer+to+a+non-array+object)), including an array of bytes. When performing pointer arithmetic, the size of the value to add to or subtract from a pointer is automatically scaled to the size of the type of the referenced array object. Adding or subtracting a scaled integer value to or from a pointer is invalid because it may yield a pointer that does not point to an element within or one past the end of the array. (See [ARR30-C. Do not form or use out-of-bounds pointers or array subscripts](https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts).) + +Adding a pointer to an array of a type other than character to the result of the `sizeof` operator or `offsetof` macro, which returns a size and an offset, respectively, violates this rule. However, adding an array pointer to the number of array elements, for example, by using the `arr[sizeof(arr)/sizeof(arr[0])])` idiom, is allowed provided that `arr` refers to an array and not a pointer. + +## Noncompliant Code Example + +In this noncompliant code example, `sizeof(buf)` is added to the array `buf`. This example is noncompliant because `sizeof(buf)` is scaled by `int` and then scaled again when added to `buf`. + +```cpp +enum { INTBUFSIZE = 80 }; + +extern int getdata(void); +int buf[INTBUFSIZE]; + +void func(void) { + int *buf_ptr = buf; + + while (buf_ptr < (buf + sizeof(buf))) { + *buf_ptr++ = getdata(); + } +} +``` + +## Compliant Solution + +This compliant solution uses an unscaled integer to obtain a pointer to the end of the array: + +```cpp +enum { INTBUFSIZE = 80 }; + +extern int getdata(void); +int buf[INTBUFSIZE]; + +void func(void) { + int *buf_ptr = buf; + + while (buf_ptr < (buf + INTBUFSIZE)) { + *buf_ptr++ = getdata(); + } +} +``` + +## Noncompliant Code Example + +In this noncompliant code example, `skip` is added to the pointer `s`. However, `skip` represents the byte offset of `ull_b` in `struct big`. When added to `s`, `skip` is scaled by the size of `struct big`. + +```cpp +#include +#include +#include + +struct big { + unsigned long long ull_a; + unsigned long long ull_b; + unsigned long long ull_c; + int si_e; + int si_f; +}; + +void func(void) { + size_t skip = offsetof(struct big, ull_b); + struct big *s = (struct big *)malloc(sizeof(struct big)); + if (s == NULL) { + /* Handle malloc() error */ + } + + memset(s + skip, 0, sizeof(struct big) - skip); + /* ... */ + free(s); + s = NULL; +} +``` + +## Compliant Solution + +This compliant solution uses an `unsigned char *` to calculate the offset instead of using a `struct big *`, which would result in scaled arithmetic: + +```cpp +#include +#include +#include + +struct big { + unsigned long long ull_a; + unsigned long long ull_b; + unsigned long long ull_c; + int si_d; + int si_e; +}; + +void func(void) { + size_t skip = offsetof(struct big, ull_b); + unsigned char *ptr = (unsigned char *)malloc( + sizeof(struct big) + ); + if (ptr == NULL) { + /* Handle malloc() error */ + } + + memset(ptr + skip, 0, sizeof(struct big) - skip); + /* ... */ + free(ptr); + ptr = NULL; +} +``` + +## Noncompliant Code Example + +In this noncompliant code example, `wcslen(error_msg) * sizeof(wchar_t)` bytes are scaled by the size of `wchar_t` when added to `error_msg`: + +```cpp +#include +#include + +enum { WCHAR_BUF = 128 }; + +void func(void) { + wchar_t error_msg[WCHAR_BUF]; + + wcscpy(error_msg, L"Error: "); + fgetws(error_msg + wcslen(error_msg) * sizeof(wchar_t), + WCHAR_BUF - 7, stdin); + /* ... */ +} +``` + +## Compliant Solution + +This compliant solution does not scale the length of the string; `wcslen()` returns the number of characters and the addition to `error_msg` is scaled: + +```cpp +#include +#include + +enum { WCHAR_BUF = 128 }; +const wchar_t ERROR_PREFIX[7] = L"Error: "; + +void func(void) { + const size_t prefix_len = wcslen(ERROR_PREFIX); + wchar_t error_msg[WCHAR_BUF]; + + wcscpy(error_msg, ERROR_PREFIX); + fgetws(error_msg + prefix_len, + WCHAR_BUF - prefix_len, stdin); + /* ... */ +} +``` + +## Risk Assessment + +Failure to understand and properly use pointer arithmetic can allow an attacker to execute arbitrary code. + +
Rule Severity Likelihood Remediation Cost Priority Level
ARR39-C High Probable High P6 L2
+ + +## Automated Detection + +
Tool Version Checker Description
Astrée 22.04 scaled-pointer-arithmetic Partially checked Besides direct rule violations, Astrée reports all (resulting) out-of-bound array accesses.
Axivion Bauhaus Suite 7.2.0 CertC-ARR39 Fully implemented
CodeSonar 7.0p0 LANG.MEM.BO LANG.MEM.BU LANG.MEM.TBA LANG.MEM.TO LANG.MEM.TULANG.STRUCT.PARITH LANG.STRUCT.PBB LANG.STRUCT.PPE BADFUNC.BO.\* Buffer overrun Buffer underrun Tainted buffer access Type overrun Type underrun Pointer Arithmetic Pointer before beginning of object Pointer past end of object A collection of warning classes that report uses of library functions prone to internal buffer overflows.
Coverity 2017.07 BAD_SIZEOF Partially implemented
Helix QAC 2022.2 C4955, C4956, C4957 C++4955, C++4956, C++4957
Klocwork 2022.2 MISRA.PTR.ARITH.2012
LDRA tool suite 9.7.1 47 S, 489 S, 567 S,64 X, 66 X, 68 X,69 X, 70 X, 71 X Partially implemented
Parasoft C/C++test 2022.1 CERT_C-ARR39-a CERT_C-ARR39-b CERT_C-ARR39-c Avoid accessing arrays out of bounds Pointer arithmetic should not be used Do not add or subtract a scaled integer to a pointer
Polyspace Bug Finder R2022a CERT C: Rule ARR39-C Checks for: Incorrect pointer scalingncorrect pointer scaling, pointer access out of boundsointer access out of bounds, possible misuse of sizeofossible misuse of sizeof. Rule partially covered.
PRQA QA-C 9.7 4955, 4956, 4957
PRQA QA-C++ 4.4 4955, 4956, 4957
RuleChecker 22.04 scaled-pointer-arithmetic Partially checked
TrustInSoft Analyzer 1.38 index_in_address Exhaustively detects undefined behavior (see one compliant and one non-compliant example ).
+ + +## Related Vulnerabilities + +Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+EXP41-C). + +## Related Guidelines + +[Key here](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions) + +
Taxonomy Taxonomy item Relationship
CERT C Secure Coding Standard ARR30-C. Do not form or use out-of-bounds pointers or array subscripts Prior to 2018-01-12: CERT: Unspecified Relationship
CERT C Secure Coding Standard ARR37-C. Do not add or subtract an integer to a pointer to a non-array object Prior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TR 24772:2013 Pointer Casting and Pointer Type Changes \[HFC\] Prior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TR 24772:2013 Pointer Arithmetic \[RVG\] Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012 Rule 18.1 (required) Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012 Rule 18.2 (required) Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012 Rule 18.3 (required) Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012 Rule 18.4 (advisory) Prior to 2018-01-12: CERT: Unspecified Relationship
CWE 2.11 CWE-468 , Incorrect Pointer Scaling 2017-07-07: CERT: Exact
+ + +## Bibliography + +
\[ Dowd 2006 \] Chapter 6, "C Language Issues"
\[ Murenin 07 \]
+ + +## Implementation notes + +None + +## References + +* CERT-C: [ARR39-C: Do not add or subtract a scaled integer to a pointer](https://wiki.sei.cmu.edu/confluence/display/c) diff --git a/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql new file mode 100644 index 0000000000..5ad9fc7f6e --- /dev/null +++ b/c/cert/src/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql @@ -0,0 +1,131 @@ +/** + * @id c/cert/do-not-add-or-subtract-a-scaled-integer-to-a-pointer + * @name ARR39-C: Do not add or subtract a scaled integer to a pointer + * @description Adding or subtracting a scaled integer value to or from a pointer may yield an + * out-of-bounds pointer. + * @kind path-problem + * @precision high + * @problem.severity error + * @tags external/cert/id/arr39-c + * correctness + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import semmle.code.cpp.dataflow.TaintTracking +import DataFlow::PathGraph + +/** + * An expression which performs pointer arithmetic + */ +abstract class PointerArithmeticExpr extends Expr { + abstract Expr getPointer(); + + abstract Expr getOperand(); +} + +/** + * A pointer arithmetic binary operation expression. + */ +class SimplePointerArithmeticExpr extends PointerArithmeticExpr, PointerArithmeticOperation { + override Expr getPointer() { result = this.getLeftOperand() } + + override Expr getOperand() { result = this.getRightOperand() } +} + +/** + * A pointer arithmetic assignment expression. + */ +class AssignPointerArithmeticExpr extends PointerArithmeticExpr, AssignOperation { + AssignPointerArithmeticExpr() { + this instanceof AssignPointerAddExpr or + this instanceof AssignPointerSubExpr + } + + override Expr getPointer() { result = this.getLValue() } + + override Expr getOperand() { result = this.getRValue() } +} + +/** + * A pointer arithmetic array access expression. + */ +class ArrayPointerArithmeticExpr extends PointerArithmeticExpr, ArrayExpr { + override Expr getPointer() { result = this.getArrayBase() } + + override Expr getOperand() { result = this.getArrayOffset() } +} + +/** + * An expression which invokes the `offsetof` macro or `__builtin_offsetof` operation. + */ +class OffsetOfExpr extends Expr { + OffsetOfExpr() { + this instanceof BuiltInOperationBuiltInOffsetOf + or + exists(MacroInvocation mi | mi.getMacroName() = "offsetof" and mi.getExpr() = this) + } +} + +/** + * An array expression conforming to the `arr[sizeof(arr)/sizeof(arr[0])]` idiom. + */ +class ArrayCountOfExpr extends ArrayExpr { + ArrayCountOfExpr() { + exists(DivExpr div, Variable arr, VariableAccess left, ArrayExpr right | + div = this.getArrayOffset() and + arr = this.getArrayBase().(VariableAccess).getTarget() and + // exclude cases where arr is a pointer rather than an array + arr.getUnderlyingType() instanceof ArrayType and + // holds if the dividend is sizeof(arr) + left = div.getLeftOperand().(SizeofExprOperator).getExprOperand() and + left.getTarget() = this.getArrayBase().(VariableAccess).getTarget() and + // holds if the divisor is sizeof(arr[0]) + right = div.getRightOperand().(SizeofExprOperator).getExprOperand() and + right.getArrayBase().(VariableAccess).getTarget() = arr and + right.getArrayOffset().(Literal).getValue() = "0" + ) + } +} + +/** + * An `offsetof` expression or a `sizeof` expression with an operand of a size greater than 1. + */ +class ScaledIntegerExpr extends Expr { + ScaledIntegerExpr() { + not this.getParent*() instanceof ArrayCountOfExpr and + ( + this.(SizeofExprOperator).getExprOperand().getType().getSize() > 1 + or + this.(SizeofTypeOperator).getTypeOperand().getSize() > 1 + or + this instanceof OffsetOfExpr + ) + } +} + +/** + * A data-flow configuration modeling data-flow from a `ScaledIntegerExpr` to a + * `PointerArithmeticExpr` where the pointer does not point to a 1-byte type. + */ +class ScaledIntegerPointerArithmeticConfig extends DataFlow::Configuration { + ScaledIntegerPointerArithmeticConfig() { this = "ScaledIntegerPointerArithmeticConfig" } + + override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ScaledIntegerExpr } + + override predicate isSink(DataFlow::Node sink) { + exists(PointerArithmeticExpr pa | + // exclude pointers to 1-byte types as they do not scale + pa.getPointer().getFullyConverted().getType().(DerivedType).getBaseType().getSize() != 1 and + pa.getOperand().getAChild*() = sink.asExpr() + ) + } +} + +from ScaledIntegerPointerArithmeticConfig config, DataFlow::PathNode src, DataFlow::PathNode sink +where + not isExcluded(sink.getNode().asExpr(), + Pointers2Package::doNotAddOrSubtractAScaledIntegerToAPointerQuery()) and + config.hasFlowPath(src, sink) +select sink, src, sink, "Scaled integer used in pointer arithmetic." diff --git a/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected new file mode 100644 index 0000000000..1d3f5dcf13 --- /dev/null +++ b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.expected @@ -0,0 +1,23 @@ +edges +| test.c:7:13:7:14 | p1 | test.c:9:9:9:10 | p1 | +| test.c:16:19:16:41 | ... - ... | test.c:18:26:18:31 | offset | +| test.c:16:19:16:41 | ... - ... | test.c:29:6:29:11 | offset | +| test.c:17:17:17:26 | sizeof() | test.c:23:9:23:12 | size | +| test.c:29:6:29:11 | offset | test.c:7:13:7:14 | p1 | +nodes +| test.c:7:13:7:14 | p1 | semmle.label | p1 | +| test.c:9:9:9:10 | p1 | semmle.label | p1 | +| test.c:16:19:16:41 | ... - ... | semmle.label | ... - ... | +| test.c:17:17:17:26 | sizeof() | semmle.label | sizeof() | +| test.c:18:26:18:31 | offset | semmle.label | offset | +| test.c:23:9:23:12 | size | semmle.label | size | +| test.c:25:9:25:18 | sizeof() | semmle.label | sizeof() | +| test.c:27:17:27:26 | sizeof() | semmle.label | sizeof() | +| test.c:29:6:29:11 | offset | semmle.label | offset | +subpaths +#select +| test.c:9:9:9:10 | p1 | test.c:16:19:16:41 | ... - ... | test.c:9:9:9:10 | p1 | Scaled integer used in pointer arithmetic. | +| test.c:18:26:18:31 | offset | test.c:16:19:16:41 | ... - ... | test.c:18:26:18:31 | offset | Scaled integer used in pointer arithmetic. | +| test.c:23:9:23:12 | size | test.c:17:17:17:26 | sizeof() | test.c:23:9:23:12 | size | Scaled integer used in pointer arithmetic. | +| test.c:25:9:25:18 | sizeof() | test.c:25:9:25:18 | sizeof() | test.c:25:9:25:18 | sizeof() | Scaled integer used in pointer arithmetic. | +| test.c:27:17:27:26 | sizeof() | test.c:27:17:27:26 | sizeof() | test.c:27:17:27:26 | sizeof() | Scaled integer used in pointer arithmetic. | diff --git a/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.qlref b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.qlref new file mode 100644 index 0000000000..3ef56dc02f --- /dev/null +++ b/c/cert/test/rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.qlref @@ -0,0 +1 @@ +rules/ARR39-C/DoNotAddOrSubtractAScaledIntegerToAPointer.ql \ No newline at end of file diff --git a/c/cert/test/rules/ARR39-C/test.c b/c/cert/test/rules/ARR39-C/test.c new file mode 100644 index 0000000000..937dce9cf5 --- /dev/null +++ b/c/cert/test/rules/ARR39-C/test.c @@ -0,0 +1,30 @@ +#include + +struct s1 { + int v1, v2, v3; +}; + +void f2(int p1, int p2) { + int *v1; + v1 += p1; // NON_COMPLIANT + v1 += p2; // COMPLIANT +} + +void f1() { + int v1[10]; + struct s1 *v2; + size_t offset = offsetof(struct s1, v2); + size_t size = sizeof(v1); + int *v3 = (int *)(v2 + offset); // NON_COMPLIANT + char *v4 = (char *)v2 + offset; // COMPLIANT + v3 = (int *)(((char *)v2) + offset); // COMPLIANT + v2++; // COMPLIANT + v2 += 10; // COMPLIANT + v3 += size; // NON_COMPLIANT + v3++; // COMPLIANT + v3 += sizeof(v1); // NON_COMPLIANT + (void)v1[sizeof(v1) / sizeof(v1[0])]; // COMPLIANT + (void)v1[10 / sizeof(v1)]; // NON_COMPLIANT + v4 += offset; // COMPLIANT + f2(offset, 2); +} \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Pointers2.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Pointers2.qll new file mode 100644 index 0000000000..d5ddafd888 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Pointers2.qll @@ -0,0 +1,25 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Pointers2Query = TDoNotAddOrSubtractAScaledIntegerToAPointerQuery() + +predicate isPointers2QueryMetadata(Query query, string queryId, string ruleId) { + query = + // `Query` instance for the `doNotAddOrSubtractAScaledIntegerToAPointer` query + Pointers2Package::doNotAddOrSubtractAScaledIntegerToAPointerQuery() and + queryId = + // `@id` for the `doNotAddOrSubtractAScaledIntegerToAPointer` query + "c/cert/do-not-add-or-subtract-a-scaled-integer-to-a-pointer" and + ruleId = "ARR39-C" +} + +module Pointers2Package { + Query doNotAddOrSubtractAScaledIntegerToAPointerQuery() { + //autogenerate `Query` type + result = + // `Query` type for `doNotAddOrSubtractAScaledIntegerToAPointer` query + TQueryC(TPointers2PackageQuery(TDoNotAddOrSubtractAScaledIntegerToAPointerQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll index c67a514009..481c399a61 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -14,6 +14,7 @@ import IO2 import IO3 import Misc import Pointers1 +import Pointers2 import Preprocessor1 import Preprocessor2 import Preprocessor3 @@ -40,6 +41,7 @@ newtype TCQuery = TIO3PackageQuery(IO3Query q) or TMiscPackageQuery(MiscQuery q) or TPointers1PackageQuery(Pointers1Query q) or + TPointers2PackageQuery(Pointers2Query q) or TPreprocessor1PackageQuery(Preprocessor1Query q) or TPreprocessor2PackageQuery(Preprocessor2Query q) or TPreprocessor3PackageQuery(Preprocessor3Query q) or @@ -66,6 +68,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId) { isIO3QueryMetadata(query, queryId, ruleId) or isMiscQueryMetadata(query, queryId, ruleId) or isPointers1QueryMetadata(query, queryId, ruleId) or + isPointers2QueryMetadata(query, queryId, ruleId) or isPreprocessor1QueryMetadata(query, queryId, ruleId) or isPreprocessor2QueryMetadata(query, queryId, ruleId) or isPreprocessor3QueryMetadata(query, queryId, ruleId) or diff --git a/rule_packages/c/Pointers2.json b/rule_packages/c/Pointers2.json new file mode 100644 index 0000000000..da275001c4 --- /dev/null +++ b/rule_packages/c/Pointers2.json @@ -0,0 +1,23 @@ +{ + "CERT-C": { + "ARR39-C": { + "properties": { + "obligation": "rule" + }, + "queries": [ + { + "description": "Adding or subtracting a scaled integer value to or from a pointer may yield an out-of-bounds pointer.", + "kind": "path-problem", + "name": "Do not add or subtract a scaled integer to a pointer", + "precision": "high", + "severity": "error", + "short_name": "DoNotAddOrSubtractAScaledIntegerToAPointer", + "tags":[ + "correctness" + ] + } + ], + "title": "Do not add or subtract a scaled integer to a pointer" + } + } +} \ No newline at end of file diff --git a/rules.csv b/rules.csv index 45393411c8..241e2f157e 100755 --- a/rules.csv +++ b/rules.csv @@ -516,16 +516,16 @@ c,CERT-C,ERR32-C,Yes,Rule,,,Do not rely on indeterminate values of errno,,Contra c,CERT-C,ERR33-C,Yes,Rule,,,Detect and handle standard library errors,MEM52-CPP,Contracts,Hard, c,CERT-C,ERR34-C,OutOfScope,Rule,,,Detect errors when converting a string to a number,,,, c,CERT-C,EXP30-C,Yes,Rule,,,Do not depend on the order of evaluation for side effects,EXP50-CPP,SideEffects1,Easy, -c,CERT-C,EXP32-C,Yes,Rule,,,Do not access a volatile object through a nonvolatile reference,,Pointers2,Easy, +c,CERT-C,EXP32-C,Yes,Rule,,,Do not access a volatile object through a nonvolatile reference,,Pointers3,Easy, c,CERT-C,EXP33-C,Yes,Rule,,,Do not read uninitialized memory,EXP53-CPP,InvalidMemory,Easy, c,CERT-C,EXP34-C,Yes,Rule,,,Do not dereference null pointers,A5-3-2,InvalidMemory,Medium, c,CERT-C,EXP35-C,Yes,Rule,,,Do not modify objects with temporary lifetime,,InvalidMemory,Hard, -c,CERT-C,EXP36-C,Yes,Rule,,,Do not cast pointers into more strictly aligned pointer types,,Pointers2,Medium, +c,CERT-C,EXP36-C,Yes,Rule,,,Do not cast pointers into more strictly aligned pointer types,,Pointers3,Medium, c,CERT-C,EXP37-C,Yes,Rule,,,Call functions with the correct number and type of arguments,,Expressions,Easy, -c,CERT-C,EXP39-C,Yes,Rule,,,Do not access a variable through a pointer of an incompatible type,,Pointers2,Medium, +c,CERT-C,EXP39-C,Yes,Rule,,,Do not access a variable through a pointer of an incompatible type,,Pointers3,Medium, c,CERT-C,EXP40-C,Yes,Rule,,,Do not modify constant objects,,Contracts,Medium, c,CERT-C,EXP42-C,Yes,Rule,,,Do not compare padding data,,Memory,Medium, -c,CERT-C,EXP43-C,Yes,Rule,,,Avoid undefined behavior when using restrict-qualified pointers,,Pointers2,Medium, +c,CERT-C,EXP43-C,Yes,Rule,,,Avoid undefined behavior when using restrict-qualified pointers,,Pointers3,Medium, c,CERT-C,EXP44-C,Yes,Rule,,,"Do not rely on side effects in operands to sizeof, _Alignof, or _Generic",M5-3-4,SideEffects1,Medium, c,CERT-C,EXP45-C,Yes,Rule,,,Do not perform assignments in selection statements,M6-2-1,SideEffects1,Medium, c,CERT-C,EXP46-C,Yes,Rule,,,Do not use a bitwise operator with a Boolean-like operand,,Expressions,Easy,