Skip to content

Commit

Permalink
Merge branch 'main' into michaelrfairhurst/add-amendments-dot-csv
Browse files Browse the repository at this point in the history
  • Loading branch information
lcartey authored Sep 25, 2024
2 parents 0ccbf48 + a51fff7 commit 224aef6
Show file tree
Hide file tree
Showing 19 changed files with 494 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,73 @@

import cpp
import codingstandards.c.misra
import codingstandards.cpp.Macro
import codingstandards.cpp.Pointers

from CStyleCast cast, Type typeFrom, Type typeTo
MacroInvocation getAMacroInvocation(CStyleCast cast) { result.getAnExpandedElement() = cast }

Macro getPrimaryMacro(CStyleCast cast) {
exists(MacroInvocation mi |
mi = getAMacroInvocation(cast) and
not exists(MacroInvocation otherMi |
otherMi = getAMacroInvocation(cast) and otherMi.getParentInvocation() = mi
) and
result = mi.getMacro()
)
}

Macro getNonFunctionPrimaryMacro(CStyleCast cast) {
result = getPrimaryMacro(cast) and
not result instanceof FunctionLikeMacro
}

from
Locatable primaryLocation, CStyleCast cast, Type typeFrom, Type typeTo, string message,
string extraMessage, Locatable optionalPlaceholderLocation, string optionalPlaceholderMessage
where
not isExcluded(cast, Pointers1Package::conversionBetweenPointerToObjectAndIntegerTypeQuery()) and
typeFrom = cast.getExpr().getUnderlyingType() and
typeTo = cast.getUnderlyingType() and
[typeFrom, typeTo] instanceof IntegralType and
[typeFrom, typeTo] instanceof PointerToObjectType and
not isNullPointerConstant(cast.getExpr())
select cast, "Cast performed between a pointer to object type and a pointer to an integer type."
(
typeFrom instanceof PointerToObjectType and
typeTo instanceof IntegralType and
message =
"Cast from pointer to object type '" + typeFrom + "' to integer type '" + typeTo + "'" +
extraMessage + "."
or
typeFrom instanceof IntegralType and
typeTo instanceof PointerToObjectType and
message =
"Cast from integer type '" + typeFrom + "' to pointer to object type '" + typeTo + "'" +
extraMessage + "."
) and
not isNullPointerConstant(cast.getExpr()) and
// If this alert is arising through a non-function-like macro expansion, flag the macro instead, to
// help make the alerts more manageable. We only do this for non-function-like macros because they
// cannot be context specific.
if exists(getNonFunctionPrimaryMacro(cast))
then
primaryLocation = getNonFunctionPrimaryMacro(cast) and
extraMessage = "" and
optionalPlaceholderLocation = primaryLocation and
optionalPlaceholderMessage = ""
else (
primaryLocation = cast and
// If the cast is in a macro expansion which is context specific, we still report the original
// location, but also add a link to the most specific macro that contains the cast, to aid
// validation.
if exists(getPrimaryMacro(cast))
then
extraMessage = " from expansion of macro $@" and
exists(Macro m |
m = getPrimaryMacro(cast) and
optionalPlaceholderLocation = m and
optionalPlaceholderMessage = m.getName()
)
else (
extraMessage = "" and
optionalPlaceholderLocation = cast and
optionalPlaceholderMessage = ""
)
)
select primaryLocation, message, optionalPlaceholderLocation, optionalPlaceholderMessage
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ where
typeTo = cast.getUnderlyingType() and
[typeFrom, typeTo] instanceof ArithmeticType and
[typeFrom, typeTo] instanceof VoidPointerType and
not isNullPointerConstant(cast.getExpr())
not cast.getExpr() instanceof Zero
select cast, "Cast performed between a pointer to void type and an arithmetic type."
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,25 @@ import codingstandards.cpp.Type
from Zero zero, Expr e, string type
where
not isExcluded(zero, Pointers1Package::macroNullNotUsedAsIntegerNullPointerConstantQuery()) and
// exclude the base-case (NULL macros and void pointer casts)
not isNullPointerConstant(zero) and
// Exclude the base-case (NULL macros and void pointer casts)
// Note: we cannot use the isNullPointerConstant predicate here because it permits
// the use of `0` without casting, which is prohibited here.
not (
zero.findRootCause() instanceof NullMacro
or
// integer constant `0` explicitly cast to void pointer
exists(Conversion c | c = zero.getConversion() |
not c.isImplicit() and
c.getUnderlyingType() instanceof VoidPointerType
)
) and
(
// ?: operator
exists(ConditionalExpr parent |
(
parent.getThen().getAChild*() = zero and parent.getElse().getType() instanceof PointerType
parent.getThen() = zero and parent.getElse().getType() instanceof PointerType
or
parent.getElse().getAChild*() = zero and parent.getThen().getType() instanceof PointerType
parent.getElse() = zero and parent.getThen().getType() instanceof PointerType
) and
// exclude a common conditional pattern used in macros such as 'assert'
not parent.isInMacroExpansion() and
Expand Down
13 changes: 10 additions & 3 deletions c/misra/src/rules/RULE-7-2/UOrUSuffixRepresentedInUnsignedType.ql
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ from Literal l
where
not isExcluded(l, SyntaxPackage::uOrUSuffixRepresentedInUnsignedTypeQuery()) and
not l instanceof StringLiteral and
l.getImplicitlyConverted().getType().(IntegralType).isUnsigned() and
not exists(l.getValueText().toUpperCase().indexOf("U"))
select l, "Unsigned literal does not explicitly express sign with a 'U' or 'u' suffix."
// Determine if the extractor deduced that the literal is unsigned, based on the C rules
l.getType().(IntegralType).isUnsigned() and
// And report if the literal does not contain a 'U' or 'u' suffix, e.g. explicitly unsigned
not exists(l.getValueText().toUpperCase().indexOf("U")) and
// Exclude constants generated by macro expansions, because the suffix information is lost in this
// case, so can cause false positives.
not l.isInMacroExpansion()
select l,
"Unsigned literal " + l.getValueText() +
" does not explicitly express sign with a 'U' or 'u' suffix."
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
| test.c:11:8:11:16 | (fp1 *)... | Cast performed between a function pointer and another type. |
| test.c:11:8:11:16 | (fp1)... | Cast performed between a function pointer and another type. |
| test.c:12:14:12:23 | (void *)... | Cast performed between a function pointer and another type. |
| test.c:14:8:14:15 | (fp2)... | Cast performed between a function pointer and another type. |
| test.c:15:8:15:15 | (fp2)... | Cast performed between a function pointer and another type. |
| test.c:22:12:22:13 | (fp1)... | Cast performed between a function pointer and another type. |
| test.c:25:8:25:9 | (fp1)... | Cast performed between a function pointer and another type. |
Expand Down
2 changes: 1 addition & 1 deletion c/misra/test/rules/RULE-11-1/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void f1(void) {
v1 = (fp1 *)v2; // NON_COMPLIANT
void *v3 = (void *)v1; // NON_COMPLIANT

v2 = (fp2 *)0; // NON_COMPLIANT
v2 = (fp2 *)0; // COMPLIANT - null pointer constant
v2 = (fp2 *)1; // NON_COMPLIANT

pfp2 v4;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
| test.c:5:21:5:42 | (unsigned int)... | Cast performed between a pointer to object type and a pointer to an integer type. |
| test.c:5:35:5:42 | (int *)... | Cast performed between a pointer to object type and a pointer to an integer type. |
| test.c:6:21:6:37 | (unsigned int)... | Cast performed between a pointer to object type and a pointer to an integer type. |
| test.c:8:8:8:24 | (unsigned int)... | Cast performed between a pointer to object type and a pointer to an integer type. |
| test.c:10:22:10:22 | (unsigned int *)... | Cast performed between a pointer to object type and a pointer to an integer type. |
| test.c:12:22:12:39 | (unsigned int *)... | Cast performed between a pointer to object type and a pointer to an integer type. |
| test.c:6:21:6:37 | (unsigned int)... | Cast from pointer to object type 'unsigned int *' to integer type 'unsigned int'. | test.c:6:21:6:37 | (unsigned int)... | |
| test.c:8:8:8:24 | (unsigned int)... | Cast from pointer to object type 'unsigned int *' to integer type 'unsigned int'. | test.c:8:8:8:24 | (unsigned int)... | |
| test.c:12:22:12:39 | (unsigned int *)... | Cast from integer type 'unsigned int' to pointer to object type 'unsigned int *'. | test.c:12:22:12:39 | (unsigned int *)... | |
| test.c:15:1:15:24 | #define FOO (int *)0x200 | Cast from integer type 'int' to pointer to object type 'int *'. | test.c:15:1:15:24 | #define FOO (int *)0x200 | |
| test.c:23:3:23:22 | (int *)... | Cast from integer type 'int' to pointer to object type 'int *' from expansion of macro $@. | test.c:17:1:17:34 | #define FOO_FUNCTIONAL(x) (int *)x | FOO_FUNCTIONAL |
| test.c:24:14:24:25 | (int *)... | Cast from integer type 'int' to pointer to object type 'int *' from expansion of macro $@. | test.c:18:1:18:23 | #define FOO_INSERT(x) x | FOO_INSERT |
16 changes: 14 additions & 2 deletions c/misra/test/rules/RULE-11-4/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@

void f1(void) {
unsigned int v1 = (unsigned int)(void *)0; // COMPLIANT
unsigned int v2 = (unsigned int)(int *)0; // NON_COMPLIANT
unsigned int v2 = (unsigned int)(int *)0; // COMPLIANT
unsigned int v3 = (unsigned int)&v2; // NON_COMPLIANT
v3 = v2; // COMPLIANT
v3 = (unsigned int)&v2; // NON_COMPLIANT
v3 = NULL; // COMPLIANT
unsigned int *v4 = 0; // NON_COMPLIANT
unsigned int *v4 = 0; // COMPLIANT
unsigned int *v5 = NULL; // COMPLIANT
unsigned int *v6 = (unsigned int *)v2; // NON_COMPLIANT
}

#define FOO (int *)0x200 // NON_COMPLIANT
#define FOO_WRAPPER FOO;
#define FOO_FUNCTIONAL(x) (int *)x
#define FOO_INSERT(x) x

void test_macros() {
FOO; // Issue is reported at the macro
FOO_WRAPPER; // Issue is reported at the macro
FOO_FUNCTIONAL(0x200); // NON_COMPLIANT
FOO_INSERT((int *)0x200); // NON_COMPLIANT
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
| test.c:15:13:15:13 | 0 | $@ uses zero-value integer constant expression as null pointer constant. | test.c:15:7:15:13 | ... == ... | Equality operator |
| test.c:17:8:17:8 | 0 | $@ uses zero-value integer constant expression as null pointer constant. | test.c:17:3:17:8 | ... = ... | Assignment to pointer |
| test.c:25:20:25:20 | 0 | $@ uses zero-value integer constant expression as null pointer constant. | test.c:25:3:25:35 | ... ? ... : ... | Ternary operator |
| test.c:25:20:25:20 | 0 | $@ uses zero-value integer constant expression as null pointer constant. | test.c:25:15:25:20 | ... = ... | Assignment to pointer |
| test.c:23:13:23:13 | 0 | $@ uses zero-value integer constant expression as null pointer constant. | test.c:23:3:23:13 | ... ? ... : ... | Ternary operator |
| test.c:24:8:24:8 | 0 | $@ uses zero-value integer constant expression as null pointer constant. | test.c:24:3:24:13 | ... ? ... : ... | Ternary operator |
| test.c:31:14:31:14 | 0 | $@ uses zero-value integer constant expression as null pointer constant. | test.c:31:9:31:14 | ... = ... | Assignment to pointer |
17 changes: 12 additions & 5 deletions c/misra/test/rules/RULE-11-9/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ void *f1(void *p1, int p2) {
p1 = NULL; // COMPLIANT
if (p2 == 0) { // COMPLIANT
return NULL;
} // COMPLIANT
(p1) ? (p1 = NULL) : (p1 = NULL); // COMPLIANT
(p2 > 0) ? (p1 = NULL) : (p1 = NULL); // COMPLIANT
(p2 > 0) ? (p1 = 0) : (p1 = NULL); // NON_COMPLIANT
return 0; // COMPLIANT
}
p2 ? p1 : 0; // NON_COMPLIANT
p2 ? 0 : p1; // NON_COMPLIANT
p2 ? (void *)0 : p1; // COMPLIANT
p2 ? p1 : (void *)0; // COMPLIANT
p2 ? p2 : 0; // COMPLIANT - p2 is not a pointer type
p2 ? 0 : p2; // COMPLIANT - p2 is not a pointer type
int x;
int *y;
p2 ? (p1 = 0) : p1; // NON_COMPLIANT - p1 is a pointer type
p2 ? (p2 = 0) : p1; // COMPLIANT - p2 is not a pointer type
return 0; // COMPLIANT
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
| test.c:8:20:8:21 | 0 | Unsigned literal does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:9:20:9:22 | 0 | Unsigned literal does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:33:6:33:6 | 1 | Unsigned literal does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:35:6:35:9 | 1 | Unsigned literal does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:37:6:37:8 | 1 | Unsigned literal does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:111:3:111:12 | 2147483648 | Unsigned literal 0x80000000 does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:116:3:116:20 | 9223372036854775808 | Unsigned literal 0x8000000000000000 does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:139:3:139:21 | 9223372036854775808 | Unsigned literal 0x8000000000000000l does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:162:3:162:21 | 9223372036854775808 | Unsigned literal 0x8000000000000000L does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:185:3:185:22 | 9223372036854775808 | Unsigned literal 0x8000000000000000ll does not explicitly express sign with a 'U' or 'u' suffix. |
| test.c:208:3:208:22 | 9223372036854775808 | Unsigned literal 0x8000000000000000LL does not explicitly express sign with a 'U' or 'u' suffix. |
Loading

0 comments on commit 224aef6

Please sign in to comment.