Skip to content

Commit 55362d0

Browse files
authored
Merge pull request #791 from github/michaelrfairhurst/concurrency6-package
Implement Concurrency6 package -- split out Concurrency7
2 parents a74e904 + 22e4fd3 commit 55362d0

37 files changed

+1156
-67
lines changed

c/cert/src/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.ql

+6-33
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,10 @@
1414

1515
import cpp
1616
import codingstandards.c.cert
17-
import codingstandards.cpp.Concurrency
17+
import codingstandards.cpp.rules.joinordetachthreadonlyonce.JoinOrDetachThreadOnlyOnce
1818

19-
// OK
20-
// 1) Thread calls detach parent DOES NOT call join
21-
// 2) Parent calls join, thread does NOT call detach()
22-
// NOT OK
23-
// 1) Thread calls detach, parent calls join
24-
// 2) Thread calls detach twice, parent does not call join
25-
// 3) Parent calls join twice, thread does not call detach
26-
from C11ThreadCreateCall tcc
27-
where
28-
not isExcluded(tcc, Concurrency5Package::threadWasPreviouslyJoinedOrDetachedQuery()) and
29-
// Note: These cases can be simplified but they are presented like this for clarity
30-
// case 1 - calls to `thrd_join` and `thrd_detach` within the parent or
31-
// within the parent / child CFG.
32-
exists(C11ThreadWait tw, C11ThreadDetach dt |
33-
tw = getAThreadContextAwareSuccessor(tcc) and
34-
dt = getAThreadContextAwareSuccessor(tcc)
35-
)
36-
or
37-
// case 2 - multiple calls to `thrd_detach` within the threaded CFG.
38-
exists(C11ThreadDetach dt1, C11ThreadDetach dt2 |
39-
dt1 = getAThreadContextAwareSuccessor(tcc) and
40-
dt2 = getAThreadContextAwareSuccessor(tcc) and
41-
not dt1 = dt2
42-
)
43-
or
44-
// case 3 - multiple calls to `thrd_join` within the threaded CFG.
45-
exists(C11ThreadWait tw1, C11ThreadWait tw2 |
46-
tw1 = getAThreadContextAwareSuccessor(tcc) and
47-
tw2 = getAThreadContextAwareSuccessor(tcc) and
48-
not tw1 = tw2
49-
)
50-
select tcc, "Thread may call join or detach after the thread is joined or detached."
19+
class ThreadWasPreviouslyJoinedOrDetachedQuery extends JoinOrDetachThreadOnlyOnceSharedQuery {
20+
ThreadWasPreviouslyJoinedOrDetachedQuery() {
21+
this = Concurrency5Package::threadWasPreviouslyJoinedOrDetachedQuery()
22+
}
23+
}

c/cert/test/rules/CON39-C/ThreadWasPreviouslyJoinedOrDetached.qlref

-1
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.ql
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
| test.c:7:18:7:39 | ATOMIC_VAR_INIT(value) | Atomic variable possibly referred to twice in an $@. | test.c:33:3:33:10 | ... += ... | expression |
22
| test.c:7:18:7:39 | ATOMIC_VAR_INIT(value) | Atomic variable possibly referred to twice in an $@. | test.c:34:3:34:13 | ... = ... | expression |
3-
| test.c:11:3:11:23 | atomic_store(a,b) | Atomic variable possibly referred to twice in an $@. | test.c:11:3:11:23 | atomic_store(a,b) | expression |
4-
| test.c:12:3:12:35 | atomic_store_explicit(a,b,c) | Atomic variable possibly referred to twice in an $@. | test.c:12:3:12:35 | atomic_store_explicit(a,b,c) | expression |
5-
| test.c:25:3:25:49 | atomic_compare_exchange_weak(a,b,c) | Atomic variable possibly referred to twice in an $@. | test.c:25:3:25:49 | atomic_compare_exchange_weak(a,b,c) | expression |
6-
| test.c:26:3:27:42 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Atomic variable possibly referred to twice in an $@. | test.c:26:3:27:42 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | expression |
3+
| test.c:11:3:11:23 | atomic_store(object,desired) | Atomic variable possibly referred to twice in an $@. | test.c:11:3:11:23 | atomic_store(object,desired) | expression |
4+
| test.c:12:3:12:23 | atomic_store_explicit | Atomic variable possibly referred to twice in an $@. | test.c:12:3:12:23 | atomic_store_explicit | expression |
5+
| test.c:25:3:25:49 | atomic_compare_exchange_weak(object,expected,desired) | Atomic variable possibly referred to twice in an $@. | test.c:25:3:25:49 | atomic_compare_exchange_weak(object,expected,desired) | expression |
6+
| test.c:26:3:26:39 | atomic_compare_exchange_weak_explicit | Atomic variable possibly referred to twice in an $@. | test.c:26:3:26:39 | atomic_compare_exchange_weak_explicit | expression |
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| test.c:6:8:6:46 | atomic_compare_exchange_weak(a,b,c) | Function that can spuriously fail not wrapped in a loop. |
2-
| test.c:10:3:10:41 | atomic_compare_exchange_weak(a,b,c) | Function that can spuriously fail not wrapped in a loop. |
3-
| test.c:12:8:13:47 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Function that can spuriously fail not wrapped in a loop. |
4-
| test.c:17:3:17:56 | atomic_compare_exchange_weak_explicit(a,b,c,d,e) | Function that can spuriously fail not wrapped in a loop. |
1+
| test.c:6:8:6:46 | atomic_compare_exchange_weak(object,expected,desired) | Function that can spuriously fail not wrapped in a loop. |
2+
| test.c:10:3:10:41 | atomic_compare_exchange_weak(object,expected,desired) | Function that can spuriously fail not wrapped in a loop. |
3+
| test.c:12:8:12:44 | atomic_compare_exchange_weak_explicit | Function that can spuriously fail not wrapped in a loop. |
4+
| test.c:17:3:17:39 | atomic_compare_exchange_weak_explicit | Function that can spuriously fail not wrapped in a loop. |
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)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.joinordetachthreadonlyonce.JoinOrDetachThreadOnlyOnce
3+
4+
class TestFileQuery extends JoinOrDetachThreadOnlyOnceSharedQuery, TestQuery { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- description: MISRA C 2012 (Audit)
2+
- qlpack: codeql/misra-c-coding-standards
3+
- include:
4+
kind:
5+
- problem
6+
- path-problem
7+
tags contain:
8+
- external/misra/c/audit
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @id c/misra/not-no-deadlocks-between-threads
3+
* @name DIR-5-2: There shall be no deadlocks between threads
4+
* @description Circular waits leading to thread deadlocks may be avoided by locking in a predefined
5+
* order.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/dir-5-2
10+
* external/misra/c/2012/amendment4
11+
* correctness
12+
* concurrency
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.c.misra
18+
import codingstandards.cpp.rules.preventdeadlockbylockinginpredefinedorder.PreventDeadlockByLockingInPredefinedOrder
19+
20+
class NotNoDeadlocksBetweenThreadsQuery extends PreventDeadlockByLockingInPredefinedOrderSharedQuery
21+
{
22+
NotNoDeadlocksBetweenThreadsQuery() {
23+
this = Concurrency6Package::notNoDeadlocksBetweenThreadsQuery()
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @id c/misra/banned-dynamic-thread-creation
3+
* @name DIR-5-3: There shall be no dynamic thread creation
4+
* @description Creating threads outside of a well-defined program start-up phase creates
5+
* uncertainty in program behavior and concurrency overhead costs.
6+
* @kind problem
7+
* @precision low
8+
* @problem.severity error
9+
* @tags external/misra/id/dir-5-3
10+
* external/misra/c/2012/amendment4
11+
* external/misra/c/audit
12+
* correctness
13+
* maintainability
14+
* concurrency
15+
* performance
16+
* external/misra/obligation/required
17+
*/
18+
19+
import cpp
20+
import codingstandards.c.misra
21+
import codingstandards.cpp.Concurrency
22+
23+
from CThreadCreateCall tc, Function enclosingFunction
24+
where
25+
not isExcluded(tc, Concurrency6Package::bannedDynamicThreadCreationQuery()) and
26+
enclosingFunction = tc.getEnclosingFunction() and
27+
not enclosingFunction.getName() = "main"
28+
select tc, "Possible dynamic creation of thread outside initialization in function '$@'.",
29+
enclosingFunction, enclosingFunction.toString()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* @id c/misra/thread-created-by-thread
3+
* @name DIR-5-3: Threads shall not be created by other threads
4+
* @description Creating threads within threads creates uncertainty in program behavior and
5+
* concurrency overhead costs.
6+
* @kind problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/misra/id/dir-5-3
10+
* external/misra/c/2012/amendment4
11+
* correctness
12+
* maintainability
13+
* concurrency
14+
* performance
15+
* external/misra/obligation/required
16+
*/
17+
18+
import cpp
19+
import codingstandards.c.misra
20+
import codingstandards.cpp.Concurrency
21+
22+
class CThreadRoot extends Function {
23+
CThreadCreateCall threadCreate;
24+
25+
CThreadRoot() { threadCreate.getFunction() = this }
26+
27+
/* Get a function which is reachable from this function */
28+
Function getAReachableFunction() { calls*(result) }
29+
30+
CThreadCreateCall getACThreadCreateCall() { result = threadCreate }
31+
}
32+
33+
from CThreadCreateCall tc, CThreadRoot threadRoot
34+
where
35+
not isExcluded(tc, Concurrency6Package::threadCreatedByThreadQuery()) and
36+
tc.getEnclosingFunction() = threadRoot.getAReachableFunction()
37+
select tc, "Thread creation call reachable from function '$@', which may also be $@.", threadRoot,
38+
threadRoot.toString(), threadRoot.getACThreadCreateCall(), "started as a thread"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @id c/misra/atomic-aggregate-object-directly-accessed
3+
* @name RULE-12-6: Structure and union members of atomic objects shall not be directly accessed
4+
* @description Accessing a member of an atomic structure or union results in undefined behavior.
5+
* @kind problem
6+
* @precision very-high
7+
* @problem.severity error
8+
* @tags external/misra/id/rule-12-6
9+
* external/misra/c/2012/amendment4
10+
* correctness
11+
* concurrency
12+
* external/misra/obligation/required
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.misra
17+
18+
from Expr expr, Field field
19+
where
20+
not isExcluded(expr, Concurrency6Package::atomicAggregateObjectDirectlyAccessedQuery()) and
21+
not expr.isUnevaluated() and
22+
(
23+
exists(FieldAccess fa |
24+
expr = fa and
25+
fa.getQualifier().getType().hasSpecifier("atomic") and
26+
field = fa.getTarget()
27+
)
28+
or
29+
exists(PointerFieldAccess fa |
30+
expr = fa and
31+
fa.getQualifier()
32+
.getType()
33+
.stripTopLevelSpecifiers()
34+
.(PointerType)
35+
.getBaseType()
36+
.hasSpecifier("atomic") and
37+
field = fa.getTarget()
38+
)
39+
)
40+
select expr, "Invalid access to member '$@' on atomic struct or union.", field, field.getName()

0 commit comments

Comments
 (0)