Skip to content

Commit fef0679

Browse files
author
Nikita Kraiouchkine
authored
Merge pull request #15 from jsinglet/jsinglet/concurrency-2-fork
Concurrency 2
2 parents e444f7c + f2765f3 commit fef0679

File tree

33 files changed

+701
-85
lines changed

33 files changed

+701
-85
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @id c/cert/deadlock-by-locking-in-predefined-order
3+
* @name CON35-C: Avoid deadlock by locking in a predefined order
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/cert/id/con35-c
10+
* correctness
11+
* concurrency
12+
* external/cert/obligation/rule
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.cert
17+
import codingstandards.cpp.rules.preventdeadlockbylockinginpredefinedorder.PreventDeadlockByLockingInPredefinedOrder
18+
19+
class DeadlockByLockingInPredefinedOrderQuery extends PreventDeadlockByLockingInPredefinedOrderSharedQuery {
20+
DeadlockByLockingInPredefinedOrderQuery() {
21+
this = Concurrency2Package::deadlockByLockingInPredefinedOrderQuery()
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @id c/cert/wrap-functions-that-can-spuriously-wake-up-in-loop
3+
* @name CON36-C: Wrap functions that can spuriously wake up in a loop
4+
* @description Not wrapping functions that can wake up spuriously in a conditioned loop can result
5+
* race conditions.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/cert/id/con36-c
10+
* correctness
11+
* concurrency
12+
* external/cert/obligation/rule
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.cert
17+
import codingstandards.cpp.rules.wrapspuriousfunctioninloop.WrapSpuriousFunctionInLoop
18+
19+
class WrapFunctionsThatCanSpuriouslyWakeUpInLoopQuery extends WrapSpuriousFunctionInLoopSharedQuery {
20+
WrapFunctionsThatCanSpuriouslyWakeUpInLoopQuery() {
21+
this = Concurrency2Package::wrapFunctionsThatCanSpuriouslyWakeUpInLoopQuery()
22+
}
23+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.ql
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/wrapspuriousfunctioninloop/WrapSpuriousFunctionInLoop.ql
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.c:15:5:15:6 | d1 | Threaded function may be called from a context that uses $@ and $@ which may lead to deadlocks. | test.c:22:3:22:10 | call to mtx_lock | lock 1 | test.c:23:3:23:10 | call to mtx_lock | lock 2 |
2+
| test.c:33:5:33:6 | d2 | Threaded function may be called from a context that uses $@ and $@ which may lead to deadlocks. | test.c:41:3:41:10 | call to mtx_lock | lock 1 | test.c:45:3:45:10 | call to mtx_lock | lock 2 |
3+
| test.c:88:5:88:6 | d4 | Threaded function may be called from a context that uses $@ and $@ which may lead to deadlocks. | test.c:111:3:111:10 | call to mtx_lock | lock 1 | test.c:112:3:112:10 | call to mtx_lock | lock 2 |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.preventdeadlockbylockinginpredefinedorder.PreventDeadlockByLockingInPredefinedOrder
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#include <stdlib.h>
2+
#include <threads.h>
3+
4+
typedef struct {
5+
int sum;
6+
mtx_t mu;
7+
} B;
8+
9+
typedef struct {
10+
B *from;
11+
B *to;
12+
int amount;
13+
} thread_arg;
14+
15+
int d1(void *arg) { // NON_COMPLIANT
16+
thread_arg *targ = (thread_arg *)arg;
17+
18+
B *from = targ->from;
19+
B *to = targ->to;
20+
int amount = targ->amount;
21+
22+
mtx_lock(&from->mu);
23+
mtx_lock(&to->mu);
24+
25+
if (from->sum >= amount) {
26+
from->sum = from->sum - amount;
27+
to->sum = to->sum + amount;
28+
return 0;
29+
}
30+
return -1;
31+
}
32+
33+
int d2(void *arg) { // NON_COMPLIANT
34+
35+
thread_arg *targ = (thread_arg *)arg;
36+
37+
B *from = targ->from;
38+
B *to = targ->to;
39+
int amount = targ->amount;
40+
41+
mtx_lock(&from->mu);
42+
if (from->sum < amount) {
43+
return -1;
44+
}
45+
mtx_lock(&to->mu);
46+
from->sum = (from->sum - amount);
47+
to->sum = (to->sum + amount);
48+
49+
return 0;
50+
}
51+
52+
int getA() { return 0; }
53+
int getARand() { return rand(); }
54+
55+
int d3(void *arg) { // COMPLIANT
56+
57+
thread_arg *targ = (thread_arg *)arg;
58+
59+
B *from = targ->from;
60+
B *to = targ->to;
61+
int amount = targ->amount;
62+
63+
mtx_t *one;
64+
mtx_t *two;
65+
66+
int a = getARand();
67+
68+
// here a may take on multiple different
69+
// values and thus different values may flow
70+
// into the locks
71+
if (a == 9) {
72+
one = &from->mu;
73+
two = &to->mu;
74+
} else {
75+
one = &to->mu;
76+
two = &from->mu;
77+
}
78+
79+
mtx_lock(one);
80+
mtx_lock(two);
81+
82+
from->sum = (from->sum - amount);
83+
to->sum = (to->sum + amount);
84+
85+
return 0;
86+
}
87+
88+
int d4(void *arg) { // NON_COMPLIANT
89+
90+
thread_arg *targ = (thread_arg *)arg;
91+
92+
B *from = targ->from;
93+
B *to = targ->to;
94+
int amount = targ->amount;
95+
96+
mtx_t *one;
97+
mtx_t *two;
98+
int a = getARand();
99+
100+
// here a may take on multiple different
101+
// values and thus different values may flow
102+
// into the locks
103+
if (a == 9) {
104+
one = &from->mu;
105+
two = &to->mu;
106+
} else {
107+
one = &to->mu;
108+
two = &from->mu;
109+
}
110+
111+
mtx_lock(&from->mu);
112+
mtx_lock(&to->mu);
113+
114+
from->sum = (from->sum - amount);
115+
to->sum = (to->sum + amount);
116+
117+
return 0;
118+
}
119+
120+
void f(B *ba1, B *ba2) {
121+
thrd_t t1, t2;
122+
123+
// unsafe - but used for testing
124+
thread_arg a1 = {.from = ba1, .to = ba2, .amount = 100};
125+
126+
thread_arg a2 = {.from = ba2, .to = ba1, .amount = 100};
127+
128+
thrd_create(&t1, d1, &a1);
129+
thrd_create(&t2, d1, &a2);
130+
}
131+
132+
void f2(B *ba1, B *ba2) {
133+
thrd_t t1, t2;
134+
135+
// unsafe - but used for testing
136+
thread_arg a1 = {.from = ba1, .to = ba2, .amount = 100};
137+
138+
thread_arg a2 = {.from = ba2, .to = ba1, .amount = 100};
139+
140+
thrd_create(&t1, d2, &a1);
141+
thrd_create(&t2, d2, &a2);
142+
}
143+
144+
void f3(B *ba1, B *ba2) {
145+
thrd_t t1, t2;
146+
147+
// unsafe - but used for testing
148+
thread_arg a1 = {.from = ba1, .to = ba2, .amount = 100};
149+
150+
thread_arg a2 = {.from = ba2, .to = ba1, .amount = 100};
151+
152+
thrd_create(&t1, d3, &a1);
153+
thrd_create(&t2, d3, &a2);
154+
}
155+
156+
void f4(B *ba1, B *ba2) {
157+
thrd_t t1, t2;
158+
159+
// unsafe - but used for testing
160+
thread_arg a1 = {.from = ba1, .to = ba2, .amount = 100};
161+
162+
thread_arg a2 = {.from = ba2, .to = ba1, .amount = 100};
163+
164+
thrd_create(&t1, d4, &a1);
165+
thrd_create(&t2, d4, &a2);
166+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.c:11:5:11:12 | call to cnd_wait | Use of a function that may wake up spuriously without a controlling loop. |
2+
| test.c:49:3:49:10 | call to cnd_wait | Use of a function that may wake up spuriously without a controlling loop. |
3+
| test.c:59:5:59:12 | call to cnd_wait | Use of a function that may wake up spuriously without a controlling loop. |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.wrapspuriousfunctioninloop.WrapSpuriousFunctionInLoop
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <stddef.h>
2+
#include <threads.h>
3+
4+
static mtx_t lk;
5+
static cnd_t cnd;
6+
7+
void f1() {
8+
mtx_lock(&lk);
9+
10+
if (1) {
11+
cnd_wait(&cnd, &lk); // NON_COMPLIANT
12+
}
13+
}
14+
15+
void f2() {
16+
mtx_lock(&lk);
17+
int i = 2;
18+
while (i > 0) {
19+
cnd_wait(&cnd, &lk); // COMPLIANT
20+
i--;
21+
}
22+
}
23+
24+
void f3() {
25+
mtx_lock(&lk);
26+
int i = 2;
27+
do {
28+
cnd_wait(&cnd, &lk); // COMPLIANT
29+
i--;
30+
} while (i > 0);
31+
}
32+
33+
void f4() {
34+
mtx_lock(&lk);
35+
36+
for (;;) {
37+
cnd_wait(&cnd, &lk); // COMPLIANT
38+
}
39+
}
40+
41+
void f5() {
42+
mtx_lock(&lk);
43+
44+
int i = 2;
45+
while (i > 0) {
46+
i--;
47+
}
48+
49+
cnd_wait(&cnd, &lk); // NON_COMPLIANT
50+
}
51+
52+
void f6() {
53+
mtx_lock(&lk);
54+
55+
for (int i = 0; i < 10; i++) {
56+
}
57+
int i = 0;
58+
if (i > 0) {
59+
cnd_wait(&cnd, &lk); // NON_COMPLIANT
60+
i--;
61+
}
62+
}

0 commit comments

Comments
 (0)