Skip to content

Commit dd96d24

Browse files
committed
C++: Model BDE single-element concurrent queue operations
1 parent b9cb90c commit dd96d24

8 files changed

Lines changed: 222 additions & 0 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added data-flow models for single-element operations on BDE `bdlcc::Deque` and `bdlcc::BoundedQueue`.

cpp/ql/lib/ext/bdlcc.model.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# BDE single-element concurrent queue operations (C++11 reference overloads).
2+
# https://github.com/bloomberg/bde/tree/ec310b87e008199ecbdbc00a0b0264a53d806a0a/groups/bdl/bdlcc
3+
extensions:
4+
- addsTo:
5+
pack: codeql/cpp-all
6+
extensible: summaryModel
7+
data:
8+
- ["BloombergLP::bdlcc", "Deque<T>", False, "pushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
9+
- ["BloombergLP::bdlcc", "Deque<T>", False, "pushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
10+
- ["BloombergLP::bdlcc", "Deque<T>", False, "pushFront", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
11+
- ["BloombergLP::bdlcc", "Deque<T>", False, "pushFront", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
12+
- ["BloombergLP::bdlcc", "Deque<T>", False, "forcePushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
13+
- ["BloombergLP::bdlcc", "Deque<T>", False, "forcePushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
14+
- ["BloombergLP::bdlcc", "Deque<T>", False, "forcePushFront", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
15+
- ["BloombergLP::bdlcc", "Deque<T>", False, "forcePushFront", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
16+
- ["BloombergLP::bdlcc", "Deque<T>", False, "tryPushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
17+
- ["BloombergLP::bdlcc", "Deque<T>", False, "tryPushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
18+
- ["BloombergLP::bdlcc", "Deque<T>", False, "popBack", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
19+
- ["BloombergLP::bdlcc", "Deque<T>", False, "popFront", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
20+
- ["BloombergLP::bdlcc", "Deque<T>", False, "tryPopBack", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
21+
- ["BloombergLP::bdlcc", "Deque<T>", False, "tryPopFront", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
22+
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "pushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
23+
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "pushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
24+
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "tryPushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
25+
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "tryPushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
26+
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "popFront", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
27+
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "tryPopFront", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
28+
- ["BloombergLP::bdlcc", "Deque", False, "popBack", "", "", "Argument[-1].Element[]", "ReturnValue", "value", "manual"]
29+
- ["BloombergLP::bdlcc", "Deque", False, "popFront", "", "", "Argument[-1].Element[]", "ReturnValue", "value", "manual"]
30+
- ["BloombergLP::bdlcc", "Deque", False, "popBack", "", "", "Argument[-1].Element[*@]", "ReturnValue[*@]", "value", "manual"]
31+
- ["BloombergLP::bdlcc", "Deque", False, "popFront", "", "", "Argument[-1].Element[*@]", "ReturnValue[*@]", "value", "manual"]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import cpp
2+
import utils.test.dataflow.FlowTestCommon
3+
import semmle.code.cpp.ir.dataflow.TaintTracking
4+
5+
module Config implements DataFlow::ConfigSig {
6+
predicate isSource(DataFlow::Node node) {
7+
node.asExpr().(FunctionCall).getTarget().hasName("source")
8+
}
9+
10+
predicate isSink(DataFlow::Node node) {
11+
exists(FunctionCall call |
12+
call.getTarget().hasName("sink") and node.asExpr() = call.getArgument(0)
13+
)
14+
}
15+
}
16+
17+
module Flow = TaintTracking::Global<Config>;
18+
19+
import MakeTest<IRFlowTest<Flow>>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Public single-element overloads from bloomberg/bde groups/bdl/bdlcc.
2+
namespace BloombergLP { namespace bslma { class Allocator; } namespace bdlcc {
3+
template<class TYPE> class Deque {
4+
public:
5+
void pushBack(const TYPE& value);
6+
void pushBack(TYPE&& value);
7+
void pushFront(const TYPE& value);
8+
void pushFront(TYPE&& value);
9+
void forcePushBack(const TYPE& value);
10+
void forcePushBack(TYPE&& value);
11+
void forcePushFront(const TYPE& value);
12+
void forcePushFront(TYPE&& value);
13+
int tryPushBack(const TYPE& value);
14+
int tryPushBack(TYPE&& value);
15+
void popBack(TYPE *value);
16+
void popFront(TYPE *value);
17+
int tryPopBack(TYPE *value);
18+
int tryPopFront(TYPE *value);
19+
TYPE popBack();
20+
TYPE popFront();
21+
template<class ITER> void forcePushBack(ITER begin, ITER end);
22+
void tryPopFront(unsigned long count);
23+
};
24+
template<class TYPE> class BoundedQueue {
25+
public:
26+
BoundedQueue(unsigned long capacity, bslma::Allocator *allocator = 0);
27+
int pushBack(const TYPE& value);
28+
int pushBack(TYPE&& value);
29+
int tryPushBack(const TYPE& value);
30+
int tryPushBack(TYPE&& value);
31+
int popFront(TYPE *value);
32+
int tryPopFront(TYPE *value);
33+
};
34+
} }
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "queues.h"
2+
int source();
3+
void sink(int);
4+
5+
struct InputIterator {
6+
int value;
7+
const int &operator*() const { return value; }
8+
};
9+
10+
// Reduced range overload body. The single-element models must not replace it.
11+
namespace BloombergLP { namespace bdlcc {
12+
template<class TYPE>
13+
template<class ITER>
14+
void Deque<TYPE>::forcePushBack(ITER begin, ITER end) {
15+
pushBack(*begin);
16+
}
17+
} }
18+
19+
void rangeOverloadKeepsItsBody() {
20+
BloombergLP::bdlcc::Deque<int> q;
21+
InputIterator begin = {source()}, end = {0};
22+
q.forcePushBack(begin, end);
23+
sink(q.popFront()); // $ ir
24+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#include "queues.h"
2+
int source();
3+
void sink(int);
4+
using namespace BloombergLP::bdlcc;
5+
6+
void DequepushBack() {
7+
Deque<int> q;
8+
int input = source(), output = 0;
9+
q.pushBack(input);
10+
q.popBack(&output);
11+
sink(output); // $ ir
12+
}
13+
void DequepushFront() {
14+
Deque<int> q;
15+
int input = source(), output = 0;
16+
q.pushFront(input);
17+
q.popFront(&output);
18+
sink(output); // $ ir
19+
}
20+
void DequeforcePushBack() {
21+
Deque<int> q;
22+
int input = source(), output = 0;
23+
q.forcePushBack(input);
24+
q.tryPopBack(&output);
25+
sink(output); // $ ir
26+
}
27+
void DequeforcePushFront() {
28+
Deque<int> q;
29+
int input = source(), output = 0;
30+
q.forcePushFront(input);
31+
q.tryPopFront(&output);
32+
sink(output); // $ ir
33+
}
34+
void DequetryPushBack() {
35+
Deque<int> q;
36+
int input = source(), output = 0;
37+
q.tryPushBack(input);
38+
q.popBack(&output);
39+
sink(output); // $ ir
40+
}
41+
void BoundedQueuepushBack() {
42+
BoundedQueue<int> q(8);
43+
int input = source(), output = 0;
44+
q.pushBack(input);
45+
q.popFront(&output);
46+
sink(output); // $ ir
47+
}
48+
void BoundedQueuetryPushBack() {
49+
BoundedQueue<int> q(8);
50+
int input = source(), output = 0;
51+
q.tryPushBack(input);
52+
q.tryPopFront(&output);
53+
sink(output); // $ ir
54+
}
55+
56+
void returnAndMove() {
57+
Deque<int> q;
58+
int input = source();
59+
q.pushBack(static_cast<int&&>(input));
60+
int output = 0;
61+
q.popBack(&output);
62+
sink(output); // $ ir
63+
sink(q.popFront()); // $ ir
64+
sink(q.popBack()); // $ ir
65+
}
66+
void returnAfterCopy() {
67+
Deque<int> q;
68+
int input = source();
69+
q.pushBack(input);
70+
sink(q.popFront()); // $ ir
71+
}
72+
void pointerPayload() {
73+
int input = source();
74+
int *p = &input, *output = 0;
75+
BoundedQueue<int*> q(8);
76+
q.pushBack(p);
77+
q.popFront(&output);
78+
sink(*output); // $ ir
79+
}
80+
void pointerReturn() {
81+
int input = source();
82+
int *p = &input;
83+
Deque<int*> q;
84+
q.pushBack(p);
85+
sink(*q.popFront()); // $ ir
86+
}
87+
struct Payload { int value; };
88+
void objectPayload() {
89+
Payload input = {source()}, output = {0};
90+
Deque<Payload> q;
91+
q.pushFront(input);
92+
q.popBack(&output);
93+
sink(output.value); // $ ir
94+
}
95+
void statusesAreNotPayload() {
96+
BoundedQueue<int> q(8);
97+
int input = source(), output = 0;
98+
sink(q.tryPushBack(input));
99+
sink(q.tryPopFront(&output));
100+
sink(output); // $ ir
101+
}
102+
void failureCanPreserveOutput() {
103+
Deque<int> q;
104+
int output = source();
105+
if (q.tryPopFront(&output) != 0)
106+
sink(output); // $ ir
107+
}

cpp/ql/test/library-tests/dataflow/external-models/validatemodels.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2437,6 +2437,7 @@
24372437
| Dubious signature "(Strent *)" in summary model. |
24382438
| Dubious signature "(Strtab *,const char *,size_t)" in summary model. |
24392439
| Dubious signature "(Strtab *,size_t *)" in summary model. |
2440+
| Dubious signature "(T &&)" in summary model. |
24402441
| Dubious signature "(T *)" in summary model. |
24412442
| Dubious signature "(T **)" in summary model. |
24422443
| Dubious signature "(TLS_FEATURE *)" in summary model. |
@@ -3691,6 +3692,7 @@
36913692
| Dubious signature "(const SSL_SESSION *,unsigned int *)" in summary model. |
36923693
| Dubious signature "(const SXNET *,unsigned char **)" in summary model. |
36933694
| Dubious signature "(const SXNETID *,unsigned char **)" in summary model. |
3695+
| Dubious signature "(const T &)" in summary model. |
36943696
| Dubious signature "(const T &,BOOL)" in summary model. |
36953697
| Dubious signature "(const TS_ACCURACY *)" in summary model. |
36963698
| Dubious signature "(const TS_ACCURACY *,unsigned char **)" in summary model. |

0 commit comments

Comments
 (0)