Skip to content

Commit 420d1c1

Browse files
committed
cpp: model BDE bdlbb::Blob byte-buffer taint flow
Add flow summaries for the BDE segmented byte buffer BloombergLP::bdlbb::Blob so taint reaches a blob's payload bytes: - Accessor chain: Blob::buffer taints the returned BlobBuffer, and BlobBuffer::data/buffer taint the bytes. - bdlbb::BlobUtil::copy and getContiguousRangeOrCopy propagate taint between a blob and a flat buffer in both directions. This unblocks blob-carried sources such as bmqa::Message::getData, whose payload was previously stranded on the opaque Blob object. Not a duplicate; the bdlbb namespace had no coverage. Verified with a BloombergLP::bdlbb-shaped stub in the dataflow external-models harness.
1 parent b756a08 commit 420d1c1

5 files changed

Lines changed: 146 additions & 2 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 flow summaries for the BDE `bdlbb::Blob` segmented byte buffer (`BloombergLP::bdlbb`). Taint now flows from a blob to its bytes through the `Blob::buffer`/`BlobBuffer::data` accessor chain and through the `bdlbb::BlobUtil::copy` and `getContiguousRangeOrCopy` helpers, so a blob populated from untrusted input (for example a BlazingMQ message body read via `bmqa::Message::getData`) is tracked into the payload bytes.

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Model of the BDE bdlbb::Blob segmented byte buffer (BloombergLP::bdlbb).
2+
# Lets taint reach a blob's payload bytes, e.g. a message body filled by bmqa::Message::getData.
3+
extensions:
4+
- addsTo:
5+
pack: codeql/cpp-all
6+
extensible: summaryModel
7+
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
8+
# Accessor chain: a tainted blob taints its buffers, and a tainted buffer taints its bytes.
9+
- ["BloombergLP::bdlbb", "Blob", true, "buffer", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
10+
- ["BloombergLP::bdlbb", "BlobBuffer", true, "data", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
11+
# BlobUtil read-out: the source blob (Argument[*1]) taints the destination buffer (and the
12+
# returned contiguous range).
13+
- ["BloombergLP::bdlbb", "BlobUtil", true, "copy", "", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
14+
- ["BloombergLP::bdlbb", "BlobUtil", true, "getContiguousRangeOrCopy", "", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
15+
- ["BloombergLP::bdlbb", "BlobUtil", true, "getContiguousRangeOrCopy", "", "", "Argument[*1]", "ReturnValue[*]", "taint", "manual"]
16+
# BlobUtil write-in: the source buffer/blob (Argument[*2]) taints the destination blob.
17+
# (`copy` is overloaded with the source at index 1 or 2; the two rows cover both layouts,
18+
# the extra one only ever reading an int offset/position argument.)
19+
- ["BloombergLP::bdlbb", "BlobUtil", true, "copy", "", "", "Argument[*2]", "Argument[*0]", "taint", "manual"]
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
// --- stub library headers ---
3+
4+
namespace bsl {
5+
typedef unsigned long size_t;
6+
template <class T> class allocator {};
7+
template<class charT> struct char_traits {};
8+
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
9+
class basic_string {
10+
public:
11+
basic_string(const charT* s, const Allocator& a = Allocator());
12+
const charT* data() const;
13+
size_t size() const;
14+
};
15+
typedef basic_string<char> string;
16+
}
17+
18+
namespace BloombergLP {
19+
namespace bdlbb {
20+
class BlobBuffer {
21+
public:
22+
char *data() const;
23+
};
24+
25+
class Blob {
26+
public:
27+
const BlobBuffer &buffer(int index) const;
28+
};
29+
30+
struct BlobUtil {
31+
static void copy(char *dstBuffer, const Blob &srcBlob, int position, int length);
32+
static void copy(Blob *dstBlob, int dstOffset, const char *srcBuffer, int length);
33+
static char *getContiguousRangeOrCopy(char *dstBuffer, const Blob &srcBlob, int position,
34+
int length, int alignment);
35+
};
36+
}
37+
}
38+
39+
// --- test code ---
40+
41+
char *source();
42+
void sink(char);
43+
44+
// A blob populated from a tainted buffer taints the bytes read back out of it.
45+
void test_BlobUtil_copy() {
46+
bsl::string s(source());
47+
BloombergLP::bdlbb::Blob blob;
48+
BloombergLP::bdlbb::BlobUtil::copy(&blob, 0, s.data(), s.size());
49+
char dst[16];
50+
BloombergLP::bdlbb::BlobUtil::copy(dst, blob, 0, 16);
51+
sink(*dst); // $ ir
52+
}
53+
54+
void test_accessor_chain() {
55+
bsl::string s(source());
56+
BloombergLP::bdlbb::Blob blob;
57+
BloombergLP::bdlbb::BlobUtil::copy(&blob, 0, s.data(), s.size());
58+
const char *p = blob.buffer(0).data();
59+
sink(*p); // $ ir
60+
}
61+
62+
void test_getContiguousRangeOrCopy() {
63+
bsl::string s(source());
64+
BloombergLP::bdlbb::Blob blob;
65+
BloombergLP::bdlbb::BlobUtil::copy(&blob, 0, s.data(), s.size());
66+
char dst[16];
67+
char *r = BloombergLP::bdlbb::BlobUtil::getContiguousRangeOrCopy(dst, blob, 0, 16, 1);
68+
sink(*r); // $ ir
69+
}

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

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,12 @@ models
9595
| 94 | Summary: Azure::Core::IO; BodyStream; true; ReadToCount; ; ; Argument[-1]; Argument[*0]; taint; manual |
9696
| 95 | Summary: Azure::Core::IO; BodyStream; true; ReadToEnd; ; ; Argument[-1]; ReturnValue.Element; taint; manual |
9797
| 96 | Summary: Azure; Nullable; true; Value; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
98-
| 97 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
98+
| 97 | Summary: BloombergLP::bdlbb; Blob; true; buffer; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
99+
| 98 | Summary: BloombergLP::bdlbb; BlobBuffer; true; data; ; ; Argument[-1]; ReturnValue[*]; taint; manual |
100+
| 99 | Summary: BloombergLP::bdlbb; BlobUtil; true; copy; ; ; Argument[*1]; Argument[*0]; taint; manual |
101+
| 100 | Summary: BloombergLP::bdlbb; BlobUtil; true; copy; ; ; Argument[*2]; Argument[*0]; taint; manual |
102+
| 101 | Summary: BloombergLP::bdlbb; BlobUtil; true; getContiguousRangeOrCopy; ; ; Argument[*1]; ReturnValue[*]; taint; manual |
103+
| 102 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
99104
edges
100105
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:56 |
101106
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | recv_buffer | provenance | Src:MaD:56 Sink:MaD:4 |
@@ -104,7 +109,7 @@ edges
104109
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | |
105110
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
106111
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | send_buffer | provenance | Sink:MaD:4 |
107-
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:97 |
112+
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:102 |
108113
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:257:5:257:8 | *resp | provenance | |
109114
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:262:5:262:8 | *resp | provenance | |
110115
| azure.cpp:253:48:253:60 | *call to GetBodyStream | azure.cpp:266:38:266:41 | *resp | provenance | |
@@ -144,6 +149,24 @@ edges
144149
| azure.cpp:294:38:294:53 | call to operator[] | azure.cpp:295:10:295:20 | contentType | provenance | |
145150
| azure.cpp:294:38:294:53 | call to operator[] | azure.cpp:295:10:295:20 | contentType | provenance | |
146151
| azure.cpp:295:10:295:20 | contentType | azure.cpp:295:10:295:20 | contentType | provenance | |
152+
| bdlbb.cpp:46:16:46:23 | call to source | bdlbb.cpp:48:49:48:52 | *call to data | provenance | TaintFunction |
153+
| bdlbb.cpp:48:37:48:41 | copy output argument | bdlbb.cpp:50:42:50:45 | *blob | provenance | |
154+
| bdlbb.cpp:48:49:48:52 | *call to data | bdlbb.cpp:48:37:48:41 | copy output argument | provenance | MaD:100 |
155+
| bdlbb.cpp:50:37:50:39 | copy output argument | bdlbb.cpp:51:7:51:10 | * ... | provenance | |
156+
| bdlbb.cpp:50:42:50:45 | *blob | bdlbb.cpp:50:37:50:39 | copy output argument | provenance | MaD:99 |
157+
| bdlbb.cpp:55:16:55:23 | call to source | bdlbb.cpp:57:49:57:52 | *call to data | provenance | TaintFunction |
158+
| bdlbb.cpp:57:37:57:41 | copy output argument | bdlbb.cpp:58:18:58:21 | *blob | provenance | |
159+
| bdlbb.cpp:57:49:57:52 | *call to data | bdlbb.cpp:57:37:57:41 | copy output argument | provenance | MaD:100 |
160+
| bdlbb.cpp:58:18:58:21 | *blob | bdlbb.cpp:58:29:58:32 | *call to buffer | provenance | MaD:97 |
161+
| bdlbb.cpp:58:18:58:38 | *call to data | bdlbb.cpp:58:18:58:38 | *call to data | provenance | |
162+
| bdlbb.cpp:58:18:58:38 | *call to data | bdlbb.cpp:59:7:59:8 | * ... | provenance | |
163+
| bdlbb.cpp:58:29:58:32 | *call to buffer | bdlbb.cpp:58:18:58:38 | *call to data | provenance | MaD:98 |
164+
| bdlbb.cpp:63:16:63:23 | call to source | bdlbb.cpp:65:49:65:52 | *call to data | provenance | TaintFunction |
165+
| bdlbb.cpp:65:37:65:41 | copy output argument | bdlbb.cpp:67:72:67:75 | *blob | provenance | |
166+
| bdlbb.cpp:65:49:65:52 | *call to data | bdlbb.cpp:65:37:65:41 | copy output argument | provenance | MaD:100 |
167+
| bdlbb.cpp:67:12:67:65 | *call to getContiguousRangeOrCopy | bdlbb.cpp:67:12:67:65 | *call to getContiguousRangeOrCopy | provenance | |
168+
| bdlbb.cpp:67:12:67:65 | *call to getContiguousRangeOrCopy | bdlbb.cpp:68:7:68:8 | * ... | provenance | |
169+
| bdlbb.cpp:67:72:67:75 | *blob | bdlbb.cpp:67:12:67:65 | *call to getContiguousRangeOrCopy | provenance | MaD:101 |
147170
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
148171
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
149172
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:48 |
@@ -532,6 +555,27 @@ nodes
532555
| azure.cpp:295:10:295:20 | contentType | semmle.label | contentType |
533556
| azure.cpp:295:10:295:20 | contentType | semmle.label | contentType |
534557
| azure.cpp:295:10:295:20 | contentType | semmle.label | contentType |
558+
| bdlbb.cpp:46:16:46:23 | call to source | semmle.label | call to source |
559+
| bdlbb.cpp:48:37:48:41 | copy output argument | semmle.label | copy output argument |
560+
| bdlbb.cpp:48:49:48:52 | *call to data | semmle.label | *call to data |
561+
| bdlbb.cpp:50:37:50:39 | copy output argument | semmle.label | copy output argument |
562+
| bdlbb.cpp:50:42:50:45 | *blob | semmle.label | *blob |
563+
| bdlbb.cpp:51:7:51:10 | * ... | semmle.label | * ... |
564+
| bdlbb.cpp:55:16:55:23 | call to source | semmle.label | call to source |
565+
| bdlbb.cpp:57:37:57:41 | copy output argument | semmle.label | copy output argument |
566+
| bdlbb.cpp:57:49:57:52 | *call to data | semmle.label | *call to data |
567+
| bdlbb.cpp:58:18:58:21 | *blob | semmle.label | *blob |
568+
| bdlbb.cpp:58:18:58:38 | *call to data | semmle.label | *call to data |
569+
| bdlbb.cpp:58:18:58:38 | *call to data | semmle.label | *call to data |
570+
| bdlbb.cpp:58:29:58:32 | *call to buffer | semmle.label | *call to buffer |
571+
| bdlbb.cpp:59:7:59:8 | * ... | semmle.label | * ... |
572+
| bdlbb.cpp:63:16:63:23 | call to source | semmle.label | call to source |
573+
| bdlbb.cpp:65:37:65:41 | copy output argument | semmle.label | copy output argument |
574+
| bdlbb.cpp:65:49:65:52 | *call to data | semmle.label | *call to data |
575+
| bdlbb.cpp:67:12:67:65 | *call to getContiguousRangeOrCopy | semmle.label | *call to getContiguousRangeOrCopy |
576+
| bdlbb.cpp:67:12:67:65 | *call to getContiguousRangeOrCopy | semmle.label | *call to getContiguousRangeOrCopy |
577+
| bdlbb.cpp:67:72:67:75 | *blob | semmle.label | *blob |
578+
| bdlbb.cpp:68:7:68:8 | * ... | semmle.label | * ... |
535579
| test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | semmle.label | *ymlStepGenerated_with_body |
536580
| test.cpp:7:47:7:52 | value2 | semmle.label | value2 |
537581
| test.cpp:7:64:7:69 | value2 | semmle.label | value2 |

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
| azure.cpp:262:5:262:8 | *resp | azure.cpp:262:23:262:28 | ReadToCount output argument |
55
| azure.cpp:287:79:287:98 | call to string | azure.cpp:287:62:287:99 | call to Url |
66
| azure.cpp:289:24:289:56 | call to GetHeader | azure.cpp:289:63:289:65 | call to Value |
7+
| bdlbb.cpp:48:49:48:52 | *call to data | bdlbb.cpp:48:37:48:41 | copy output argument |
8+
| bdlbb.cpp:50:42:50:45 | *blob | bdlbb.cpp:50:37:50:39 | copy output argument |
9+
| bdlbb.cpp:57:49:57:52 | *call to data | bdlbb.cpp:57:37:57:41 | copy output argument |
10+
| bdlbb.cpp:58:18:58:21 | *blob | bdlbb.cpp:58:29:58:32 | *call to buffer |
11+
| bdlbb.cpp:58:29:58:32 | *call to buffer | bdlbb.cpp:58:18:58:38 | *call to data |
12+
| bdlbb.cpp:65:49:65:52 | *call to data | bdlbb.cpp:65:37:65:41 | copy output argument |
13+
| bdlbb.cpp:67:72:67:75 | *blob | bdlbb.cpp:67:12:67:65 | *call to getContiguousRangeOrCopy |
14+
| bdlbb.cpp:67:72:67:75 | *blob | bdlbb.cpp:67:67:67:69 | getContiguousRangeOrCopy output argument |
715
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual |
816
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated |
917
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |

0 commit comments

Comments
 (0)