Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cpp/ql/lib/change-notes/2026-09-14-bdlcc-models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added data-flow models for single-element operations on BDE `bdlcc::Deque` and `bdlcc::BoundedQueue`.
31 changes: 31 additions & 0 deletions cpp/ql/lib/ext/bdlcc.model.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# BDE single-element concurrent queue operations (C++11 reference overloads).
# https://github.com/bloomberg/bde/tree/ec310b87e008199ecbdbc00a0b0264a53d806a0a/groups/bdl/bdlcc
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data:
- ["BloombergLP::bdlcc", "Deque<T>", False, "pushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "pushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "pushFront", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "pushFront", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "forcePushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "forcePushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "forcePushFront", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "forcePushFront", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "tryPushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "tryPushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
Comment on lines +16 to +17
- ["BloombergLP::bdlcc", "Deque<T>", False, "popBack", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "popFront", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "tryPopBack", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque<T>", False, "tryPopFront", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "pushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "pushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "tryPushBack", "(const T &)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "tryPushBack", "(T &&)", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "popFront", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
- ["BloombergLP::bdlcc", "BoundedQueue<T>", False, "tryPopFront", "(T *)", "", "Argument[-1].Element[@]", "Argument[*@0]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque", False, "popBack", "", "", "Argument[-1].Element[]", "ReturnValue", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque", False, "popFront", "", "", "Argument[-1].Element[]", "ReturnValue", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque", False, "popBack", "", "", "Argument[-1].Element[*@]", "ReturnValue[*@]", "value", "manual"]
- ["BloombergLP::bdlcc", "Deque", False, "popFront", "", "", "Argument[-1].Element[*@]", "ReturnValue[*@]", "value", "manual"]
1 change: 1 addition & 0 deletions cpp/ql/test/library-tests/dataflow/bdlcc/flow.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

19 changes: 19 additions & 0 deletions cpp/ql/test/library-tests/dataflow/bdlcc/flow.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import cpp
import utils.test.dataflow.FlowTestCommon
import semmle.code.cpp.ir.dataflow.TaintTracking

module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
node.asExpr().(FunctionCall).getTarget().hasName("source")
}

predicate isSink(DataFlow::Node node) {
exists(FunctionCall call |
call.getTarget().hasName("sink") and node.asExpr() = call.getArgument(0)
)
}
}

module Flow = TaintTracking::Global<Config>;

import MakeTest<IRFlowTest<Flow>>
34 changes: 34 additions & 0 deletions cpp/ql/test/library-tests/dataflow/bdlcc/queues.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Public single-element overloads from bloomberg/bde groups/bdl/bdlcc.
namespace BloombergLP { namespace bslma { class Allocator; } namespace bdlcc {
template<class TYPE> class Deque {
public:
void pushBack(const TYPE& value);
void pushBack(TYPE&& value);
void pushFront(const TYPE& value);
void pushFront(TYPE&& value);
void forcePushBack(const TYPE& value);
void forcePushBack(TYPE&& value);
void forcePushFront(const TYPE& value);
void forcePushFront(TYPE&& value);
int tryPushBack(const TYPE& value);
int tryPushBack(TYPE&& value);
void popBack(TYPE *value);
void popFront(TYPE *value);
int tryPopBack(TYPE *value);
int tryPopFront(TYPE *value);
TYPE popBack();
TYPE popFront();
template<class ITER> void forcePushBack(ITER begin, ITER end);
void tryPopFront(unsigned long count);
};
template<class TYPE> class BoundedQueue {
public:
BoundedQueue(unsigned long capacity, bslma::Allocator *allocator = 0);
int pushBack(const TYPE& value);
int pushBack(TYPE&& value);
int tryPushBack(const TYPE& value);
int tryPushBack(TYPE&& value);
int popFront(TYPE *value);
int tryPopFront(TYPE *value);
};
} }
24 changes: 24 additions & 0 deletions cpp/ql/test/library-tests/dataflow/bdlcc/ranges.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "queues.h"
int source();
void sink(int);

struct InputIterator {
int value;
const int &operator*() const { return value; }
};

// Reduced range overload body. The single-element models must not replace it.
namespace BloombergLP { namespace bdlcc {
template<class TYPE>
template<class ITER>
void Deque<TYPE>::forcePushBack(ITER begin, ITER end) {
pushBack(*begin);
}
} }

void rangeOverloadKeepsItsBody() {
BloombergLP::bdlcc::Deque<int> q;
InputIterator begin = {source()}, end = {0};
q.forcePushBack(begin, end);
sink(q.popFront()); // $ ir
}
107 changes: 107 additions & 0 deletions cpp/ql/test/library-tests/dataflow/bdlcc/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include "queues.h"
int source();
void sink(int);
using namespace BloombergLP::bdlcc;

void DequepushBack() {
Deque<int> q;
int input = source(), output = 0;
q.pushBack(input);
q.popBack(&output);
sink(output); // $ ir
}
void DequepushFront() {
Deque<int> q;
int input = source(), output = 0;
q.pushFront(input);
q.popFront(&output);
sink(output); // $ ir
}
void DequeforcePushBack() {
Deque<int> q;
int input = source(), output = 0;
q.forcePushBack(input);
q.tryPopBack(&output);
sink(output); // $ ir
}
void DequeforcePushFront() {
Deque<int> q;
int input = source(), output = 0;
q.forcePushFront(input);
q.tryPopFront(&output);
sink(output); // $ ir
}
void DequetryPushBack() {
Deque<int> q;
int input = source(), output = 0;
q.tryPushBack(input);
q.popBack(&output);
sink(output); // $ ir
}
void BoundedQueuepushBack() {
BoundedQueue<int> q(8);
int input = source(), output = 0;
q.pushBack(input);
q.popFront(&output);
sink(output); // $ ir
}
void BoundedQueuetryPushBack() {
BoundedQueue<int> q(8);
int input = source(), output = 0;
q.tryPushBack(input);
q.tryPopFront(&output);
sink(output); // $ ir
}

void returnAndMove() {
Deque<int> q;
int input = source();
q.pushBack(static_cast<int&&>(input));
int output = 0;
q.popBack(&output);
sink(output); // $ ir
sink(q.popFront()); // $ ir
sink(q.popBack()); // $ ir
}
void returnAfterCopy() {
Deque<int> q;
int input = source();
q.pushBack(input);
sink(q.popFront()); // $ ir
}
void pointerPayload() {
int input = source();
int *p = &input, *output = 0;
BoundedQueue<int*> q(8);
q.pushBack(p);
q.popFront(&output);
sink(*output); // $ ir
}
void pointerReturn() {
int input = source();
int *p = &input;
Deque<int*> q;
q.pushBack(p);
sink(*q.popFront()); // $ ir
}
struct Payload { int value; };
void objectPayload() {
Payload input = {source()}, output = {0};
Deque<Payload> q;
q.pushFront(input);
q.popBack(&output);
sink(output.value); // $ ir
}
void statusesAreNotPayload() {
BoundedQueue<int> q(8);
int input = source(), output = 0;
sink(q.tryPushBack(input));
sink(q.tryPopFront(&output));
sink(output); // $ ir
}
void failureCanPreserveOutput() {
Deque<int> q;
int output = source();
if (q.tryPopFront(&output) != 0)
sink(output); // $ ir
}
Original file line number Diff line number Diff line change
Expand Up @@ -2437,6 +2437,7 @@
| Dubious signature "(Strent *)" in summary model. |
| Dubious signature "(Strtab *,const char *,size_t)" in summary model. |
| Dubious signature "(Strtab *,size_t *)" in summary model. |
| Dubious signature "(T &&)" in summary model. |
| Dubious signature "(T *)" in summary model. |
| Dubious signature "(T **)" in summary model. |
| Dubious signature "(TLS_FEATURE *)" in summary model. |
Expand Down Expand Up @@ -3691,6 +3692,7 @@
| Dubious signature "(const SSL_SESSION *,unsigned int *)" in summary model. |
| Dubious signature "(const SXNET *,unsigned char **)" in summary model. |
| Dubious signature "(const SXNETID *,unsigned char **)" in summary model. |
| Dubious signature "(const T &)" in summary model. |
| Dubious signature "(const T &,BOOL)" in summary model. |
| Dubious signature "(const TS_ACCURACY *)" in summary model. |
| Dubious signature "(const TS_ACCURACY *,unsigned char **)" in summary model. |
Expand Down