CERT.CONC.UNSAFE_COND_VAR

条件変数の使用時にはスレッドセーフと活性を維持してください。

wait() 関数は、条件述語が当てはまるかをチェックするループから呼び出す必要があります。条件述語は関数の変数から構成された式です。スレッドを継続的に実行させるには、条件述語が真でなければなりません。

脆弱性とリスク

条件述語ループでネストして wait() を呼び出さないと、通知を受け取った後、チェッカーは条件述語のチェックを行いません。通知が偽物であったり、悪意のあるものであった場合、スレッドが早々に起動する可能性があります。

軽減と防止

wait() 関数は、条件述語が当てはまるかをチェックするループから呼び出す必要があります。

1  #include <condition_variable>
2  #include <mutex>
3  
4  struct Node {
5    void *node;
6    struct Node *next;
7  };
8  
9  static Node list;
10 static std::mutex m;
11 static std::condition_variable condition;
12 
13 void consume_list_element1(std::condition_variable &condition) {
14   std::unique_lock<std::mutex> lk(m);
15 
16   if (list.next == nullptr) {
17     condition.wait(lk);          // Uncompliant code.
18   }
19 
20   // Proceed when condition holds.
21 }
22 
23 void consume_list_element2() {
24   std::unique_lock<std::mutex> lk(m);
25 
26   while (list.next == nullptr) {
27     condition.wait(lk);         // Compliant code
28   }
29 
30   // Proceed when condition holds.
31 }
32 
33 void consume_list_element3() {
34   std::unique_lock<std::mutex> lk(m);
35 
36   condition.wait(lk, []{ return list.next; });       //Compliant code.
37   // Proceed when condition holds.
38 }