Skip to content

Commit ae63dcb

Browse files
Implement most MISRA-C amendment4 rule amendments
1 parent 89bd9b4 commit ae63dcb

File tree

22 files changed

+307
-31
lines changed

22 files changed

+307
-31
lines changed

amendments.csv

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ c,MISRA-C-2012,Amendment3,RULE-10-7,Yes,Refine,No,Import
1111
c,MISRA-C-2012,Amendment3,RULE-10-8,Yes,Refine,No,Import
1212
c,MISRA-C-2012,Amendment3,RULE-21-11,Yes,Clarification,No,Import
1313
c,MISRA-C-2012,Amendment3,RULE-21-12,Yes,Replace,No,Easy
14-
c,MISRA-C-2012,Amendment4,RULE-11-3,Yes,Expand,No,Easy
15-
c,MISRA-C-2012,Amendment4,RULE-11-8,Yes,Expand,No,Easy
16-
c,MISRA-C-2012,Amendment4,RULE-13-2,Yes,Expand,No,Very Hard
14+
c,MISRA-C-2012,Amendment4,RULE-11-3,Yes,Expand,Yes,Easy
15+
c,MISRA-C-2012,Amendment4,RULE-11-8,Yes,Expand,Yes,Easy
16+
c,MISRA-C-2012,Amendment4,RULE-13-2,Yes,Expand,Yes,Very Hard
1717
c,MISRA-C-2012,Amendment4,RULE-18-6,Yes,Expand,No,Medium
1818
c,MISRA-C-2012,Amendment4,RULE-18-8,Yes,Split,Yes,Easy
1919
c,MISRA-C-2012,Corrigendum2,RULE-2-2,Yes,Clarification,No,Import
2020
c,MISRA-C-2012,Corrigendum2,RULE-2-7,Yes,Clarification,No,Import
21-
c,MISRA-C-2012,Corrigendum2,RULE-3-1,Yes,Refine,No,Easy
21+
c,MISRA-C-2012,Corrigendum2,RULE-3-1,Yes,Refine,Yes,Easy
2222
c,MISRA-C-2012,Corrigendum2,RULE-8-6,Yes,Clarification,No,Import
2323
c,MISRA-C-2012,Corrigendum2,RULE-8-9,Yes,Clarification,No,Import
2424
c,MISRA-C-2012,Corrigendum2,RULE-9-4,Yes,Clarification,No,Import
2525
c,MISRA-C-2012,Corrigendum2,RULE-10-1,Yes,Clarification,No,Import
2626
c,MISRA-C-2012,Corrigendum2,RULE-18-3,Yes,Clarification,No,Import
2727
c,MISRA-C-2012,Corrigendum2,RULE-1-4,Yes,Replace,No,Easy
28-
c,MISRA-C-2012,Corrigendum2,RULE-9-1,Yes,Refine,No,Easy
28+
c,MISRA-C-2012,Corrigendum2,RULE-9-1,Yes,Refine,Yes,Easy
2929
c,MISRA-C-2012,Corrigendum2,RULE-9-2,Yes,Refine,No,Import
3030
c,MISRA-C-2012,Corrigendum2,DIR-4-10,Yes,Clarification,No,Import
3131
c,MISRA-C-2012,Corrigendum2,RULE-7-4,Yes,Refine,No,Easy
Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,69 @@
1-
#define atomic_compare_exchange_weak(a, b, c) 0
2-
#define atomic_compare_exchange_weak_explicit(a, b, c, d, e) 0
3-
#define atomic_load(a) 0
4-
#define atomic_load_explicit(a, b)
5-
#define atomic_store(a, b) 0
6-
#define atomic_store_explicit(a, b, c) 0
71
#define ATOMIC_VAR_INIT(value) (value)
82
#define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj)))
9-
typedef _Atomic(int) atomic_int;
3+
typedef _Atomic(int) atomic_int;
4+
5+
#define __ATOMIC_RELAXED 0
6+
#define __ATOMIC_CONSUME 1
7+
#define __ATOMIC_ACQUIRE 2
8+
#define __ATOMIC_RELEASE 3
9+
#define __ATOMIC_ACQ_REL 4
10+
#define __ATOMIC_SEQ_CST 5
11+
12+
typedef enum memory_order {
13+
memory_order_relaxed = __ATOMIC_RELAXED,
14+
memory_order_consume = __ATOMIC_CONSUME,
15+
memory_order_acquire = __ATOMIC_ACQUIRE,
16+
memory_order_release = __ATOMIC_RELEASE,
17+
memory_order_acq_rel = __ATOMIC_ACQ_REL,
18+
memory_order_seq_cst = __ATOMIC_SEQ_CST
19+
} memory_order;
20+
21+
void atomic_thread_fence(memory_order);
22+
void atomic_signal_fence(memory_order);
23+
24+
#define atomic_thread_fence(order) __c11_atomic_thread_fence(order)
25+
#define atomic_signal_fence(order) __c11_atomic_signal_fence(order)
26+
27+
#define atomic_store(object, desired) __c11_atomic_store(object, desired, __ATOMIC_SEQ_CST)
28+
#define atomic_store_explicit __c11_atomic_store
29+
30+
#define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
31+
#define atomic_load_explicit __c11_atomic_load
32+
33+
#define atomic_exchange(object, desired) __c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST)
34+
#define atomic_exchange_explicit __c11_atomic_exchange
35+
36+
#define atomic_compare_exchange_strong(object, expected, desired) __c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
37+
#define atomic_compare_exchange_strong_explicit __c11_atomic_compare_exchange_strong
38+
39+
#define atomic_compare_exchange_weak(object, expected, desired) __c11_atomic_compare_exchange_weak(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
40+
#define atomic_compare_exchange_weak_explicit __c11_atomic_compare_exchange_weak
41+
42+
#define atomic_fetch_add(object, operand) __c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
43+
#define atomic_fetch_add_explicit __c11_atomic_fetch_add
44+
45+
#define atomic_fetch_sub(object, operand) __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
46+
#define atomic_fetch_sub_explicit __c11_atomic_fetch_sub
47+
48+
#define atomic_fetch_or(object, operand) __c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST)
49+
#define atomic_fetch_or_explicit __c11_atomic_fetch_or
50+
51+
#define atomic_fetch_xor(object, operand) __c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST)
52+
#define atomic_fetch_xor_explicit __c11_atomic_fetch_xor
53+
54+
#define atomic_fetch_and(object, operand) __c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
55+
#define atomic_fetch_and_explicit __c11_atomic_fetch_and
56+
57+
typedef struct atomic_flag { _Atomic(_Bool) _Value; } atomic_flag;
58+
59+
_Bool atomic_flag_test_and_set(volatile atomic_flag *);
60+
_Bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order);
61+
62+
void atomic_flag_clear(volatile atomic_flag *);
63+
void atomic_flag_clear_explicit(volatile atomic_flag *, memory_order);
64+
65+
#define atomic_flag_test_and_set(object) __c11_atomic_exchange(&(object)->_Value, 1, __ATOMIC_SEQ_CST)
66+
#define atomic_flag_test_and_set_explicit(object, order) __c11_atomic_exchange(&(object)->_Value, 1, order)
67+
68+
#define atomic_flag_clear(object) __c11_atomic_store(&(object)->_Value, 0, __ATOMIC_SEQ_CST)
69+
#define atomic_flag_clear_explicit(object, order) __c11_atomic_store(&(object)->_Value, 0, order)

c/common/test/rules/readofuninitializedmemory/test.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,6 @@ void test_non_default_init() {
9494
static struct A ss;
9595
use_struct_A(
9696
ss); // COMPLIANT - static struct type variables are zero initialized
97+
_Atomic int x;
98+
use_int(x); // COMPLIANT - atomics are special, covered by other rules
9799
}

c/misra/src/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.ql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ where
2323
baseTypeFrom = cast.getExpr().getType().(PointerToObjectType).getBaseType() and
2424
baseTypeTo = cast.getType().(PointerToObjectType).getBaseType() and
2525
// exception: cast to a char, signed char, or unsigned char is permitted
26-
not baseTypeTo.stripType() instanceof CharType and
26+
not (
27+
baseTypeTo.stripType() instanceof CharType and
28+
// Exception does not apply to _Atomic types
29+
not baseTypeFrom.hasSpecifier("atomic")
30+
) and
2731
(
2832
(
2933
baseTypeFrom.isVolatile() and not baseTypeTo.isVolatile()

c/misra/src/rules/RULE-11-8/CastRemovesConstOrVolatileQualification.ql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,9 @@ where
2424
baseTypeFrom.isVolatile() and not baseTypeTo.isVolatile() and qualificationName = "volatile"
2525
or
2626
baseTypeFrom.isConst() and not baseTypeTo.isConst() and qualificationName = "const"
27+
or
28+
baseTypeFrom.hasSpecifier("atomic") and
29+
not baseTypeTo.hasSpecifier("atomic") and
30+
qualificationName = "atomic"
2731
)
2832
select cast, "Cast of pointer removes " + qualificationName + " qualification from its base type."
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* @id c/misra/unsequenced-atomic-reads
3+
* @name RULE-13-2: The value of an atomic variable depend on its evaluation order and interleave of threads
4+
* @description The value of an atomic variable shall not depend on evaluation order and
5+
* interleaving of threads.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-13-2
10+
* correctness
11+
* external/misra/c/2012/amendment3
12+
* external/misra/obligation/required
13+
*/
14+
15+
import cpp
16+
import semmle.code.cpp.dataflow.TaintTracking
17+
import codingstandards.c.misra
18+
import codingstandards.c.Ordering
19+
import codingstandards.c.orderofevaluation.VariableAccessOrdering
20+
21+
class AtomicAccessInFullExpressionOrdering extends Ordering::Configuration {
22+
AtomicAccessInFullExpressionOrdering() { this = "AtomicAccessInFullExpressionOrdering" }
23+
24+
override predicate isCandidate(Expr e1, Expr e2) {
25+
exists(AtomicVariableAccess a, AtomicVariableAccess b, FullExpr e | a = e1 and b = e2 |
26+
a.getTarget() = b.getTarget() and
27+
a.(ConstituentExpr).getFullExpr() = e and
28+
b.(ConstituentExpr).getFullExpr() = e and
29+
not a = b
30+
)
31+
}
32+
}
33+
34+
/**
35+
* A read of a variable specified as `_Atomic`.
36+
*
37+
* Note, it may be accessed directly, or by passing its address into the std atomic functions.
38+
*/
39+
class AtomicVariableAccess extends VariableAccess {
40+
pragma[noinline]
41+
AtomicVariableAccess() {
42+
getTarget().getType().hasSpecifier("atomic")
43+
}
44+
45+
/* Get the `atomic_<read|write>()` call this VarAccess occurs in. */
46+
FunctionCall getAtomicFunctionCall() {
47+
exists(AddressOfExpr addrParent, FunctionCall fc |
48+
fc.getTarget().getName().matches("__c11_atomic%") and
49+
addrParent = fc.getArgument(0) and
50+
addrParent.getAnOperand() = this
51+
and result = fc
52+
)
53+
}
54+
55+
/**
56+
* Gets an assigned expr, either in the form `x = <result>` or `atomic_store(&x, <result>)`.
57+
*/
58+
Expr getAnAssignedExpr() {
59+
result = getAtomicFunctionCall().getArgument(1)
60+
or
61+
exists(AssignExpr assign |
62+
assign.getLValue() = this
63+
and result = assign.getRValue()
64+
)
65+
}
66+
67+
/**
68+
* Gets the expression holding this variable access, either in the form `x` or `atomic_read(&x)`.
69+
*/
70+
Expr getARead() {
71+
result = getAtomicFunctionCall()
72+
or
73+
result = this
74+
}
75+
}
76+
77+
from
78+
AtomicAccessInFullExpressionOrdering config, FullExpr e, Variable v,
79+
AtomicVariableAccess va1, AtomicVariableAccess va2
80+
where
81+
not isExcluded(e, SideEffects3Package::unsequencedAtomicReadsQuery()) and
82+
e = va1.(ConstituentExpr).getFullExpr() and
83+
config.isUnsequenced(va1, va2) and
84+
v = va1.getTarget() and
85+
v = va2.getTarget() and
86+
// Exclude cases where the variable is assigned a value tainted by the other variable access.
87+
not exists(Expr write |
88+
write = va1.getAnAssignedExpr() and
89+
TaintTracking::localTaint(DataFlow::exprNode(va2.getARead()), DataFlow::exprNode(write))
90+
) and
91+
// Impose an ordering, show the first access.
92+
va1.getLocation().isBefore(va2.getLocation(), _)
93+
select e, "Atomic variable $@ has a $@ that is unsequenced with $@.",
94+
v, v.getName(), va1, "previous read", va2, "another read"

c/misra/src/rules/RULE-3-1/CharacterSequencesAndUsedWithinAComment.ql

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,38 @@
1616
import cpp
1717
import codingstandards.c.misra
1818

19-
class IllegalCCommentCharacter extends string {
20-
IllegalCCommentCharacter() {
21-
this = "/*" or
22-
this = "//"
23-
}
19+
/* Character sequence is banned from all comment types */
20+
class IllegalCommentSequence extends string {
21+
IllegalCommentSequence() { this = "/*" }
2422
}
2523

26-
class IllegalCPPCommentCharacter extends string {
27-
IllegalCPPCommentCharacter() { this = "/*" }
24+
/* A regexp to check for illegal C-style comments */
25+
class IllegalCCommentRegexp extends string {
26+
IllegalCCommentRegexp() {
27+
// Regexp to match "//" in C-style comments, which do not appear to be URLs. General format
28+
// uses negative lookahead/lookbehind to match like `.*(?<!HTTP:)//(?!GITHUB.).*`. Broken down
29+
// into parts:
30+
// - `.*PATTERN.*` - look for the pattern anywhere in the comment.
31+
// - `(?<![a-zA-Z]:)` - negative lookbehind, exclude "http://github.com" by seeing "p:".
32+
// - `//` - the actual illegal sequence.
33+
// - `(?!(pattern))` - negative lookahead, exclude "http://github.com" by seeing "github.".
34+
// - `[a-zA-Z0-9\\-]+\\\\.` - Assume alphanumeric/hyphen followed by '.' is a domain name.
35+
this = ".*(?<![a-zA-Z]:)//(?![a-zA-Z0-9\\-]+\\\\.).*"
36+
}
37+
38+
string getDescription() { result = "//" }
2839
}
2940

3041
from Comment comment, string illegalSequence
3142
where
3243
not isExcluded(comment, SyntaxPackage::characterSequencesAndUsedWithinACommentQuery()) and
3344
(
34-
exists(IllegalCCommentCharacter c | illegalSequence = c |
35-
comment.(CStyleComment).getContents().indexOf(illegalSequence) > 0
45+
exists(IllegalCommentSequence c | illegalSequence = c |
46+
comment.getContents().indexOf(illegalSequence) > 0
3647
)
3748
or
38-
exists(IllegalCPPCommentCharacter c | illegalSequence = c |
39-
comment.(CppStyleComment).getContents().indexOf(illegalSequence) > 0
49+
exists(IllegalCCommentRegexp c | illegalSequence = c.getDescription() |
50+
comment.(CStyleComment).getContents().regexpMatch(c)
4051
)
4152
)
4253
select comment, "Comment contains an illegal sequence '" + illegalSequence + "'"

c/misra/test/rules/RULE-11-3/CastBetweenObjectPointerAndDifferentObjectType.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@
66
| test.c:21:3:21:16 | (int *)... | Cast performed between a pointer to object type (char) and a pointer to a different object type (int). |
77
| test.c:22:20:22:21 | (int *)... | Cast performed between a pointer to object type (char) and a pointer to a different object type (int). |
88
| test.c:23:3:23:18 | (long long *)... | Cast performed between a pointer to object type (int) and a pointer to a different object type (long long). |
9+
| test.c:26:3:26:13 | (char *)... | Cast performed between a pointer to object type (_Atomic(int)) and a pointer to a different object type (char). |
10+
| test.c:27:8:27:10 | (char *)... | Cast performed between a pointer to object type (_Atomic(int)) and a pointer to a different object type (char). |
11+
| test.c:28:3:28:21 | (_Atomic(char) *)... | Cast performed between a pointer to object type (_Atomic(int)) and a pointer to a different object type (_Atomic(char)). |
12+
| test.c:29:23:29:25 | (_Atomic(char) *)... | Cast performed between a pointer to object type (_Atomic(int)) and a pointer to a different object type (_Atomic(char)). |

c/misra/test/rules/RULE-11-3/test.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,10 @@ void f1(void) {
2121
(int *const)v2; // NON_COMPLIANT
2222
int *const v10 = v2; // NON_COMPLIANT
2323
(long long *)v10; // NON_COMPLIANT
24+
25+
_Atomic int *v11 = 0;
26+
(char *)v11; // NON_COMPLIANT
27+
v2 = v11; // NON_COMPLIANT
28+
(_Atomic char *)v11; // NON_COMPLIANT
29+
_Atomic char *v12 = v11; // NON_COMPLIANT
2430
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
| test.c:4:19:4:33 | (const char *)... | Cast of pointer removes volatile qualification from its base type. |
22
| test.c:6:13:6:21 | (char *)... | Cast of pointer removes const qualification from its base type. |
3+
| test.c:9:3:9:11 | (char *)... | Cast of pointer removes atomic qualification from its base type. |
4+
| test.c:10:7:10:7 | (char *)... | Cast of pointer removes atomic qualification from its base type. |
5+
| test.c:11:3:11:17 | (const char *)... | Cast of pointer removes atomic qualification from its base type. |
6+
| test.c:12:7:12:7 | (const char *)... | Cast of pointer removes atomic qualification from its base type. |

0 commit comments

Comments
 (0)